// vim: ts=4:sw=4
// gvim: ts=4:sw=4
function hasOwnProperty(obj, prop){
	var proto = obj.__proto__ || obj.constructor.prototype;
	return (prop in obj) && (!(prop in proto) || proto[prop] !== obj[prop]);
} 

// Register namespaces and their corresponding paths to Ext.Loader
Ext.Loader.setPath({
    'AppName': 'myappname'
    // Other namespaces
});

Ext.Loader.setConfig({
    enabled: true
});

var ux_path="";
if(window.griglobs_EXTJS4_URLPREFIX !== undefined) {
	// Ext.Loader.setPath('Ext.ux','/ux');
	if(griglobs_EXTJS4_URLPREFIX.substr(0,1) == '/') {
		ux_path=window.griglobs_EXTJS4_URLPREFIX.substr(1,
			window.griglobs_EXTJS4_URLPREFIX.length-1) + '/ux';
	} else {
		ux_path=window.griglobs_EXTJS4_URLPREFIX + '/ux';
	}
} else {
	ux_path='../ux';
}
ux_path='ux';
console.log("ux_path set to: " + ux_path);
Ext.Loader.setPath('Ext.ux',ux_path);

// Specify a list of classes your application your application needs
Ext.require([
	'Ext.window.Window',
	'Ext.Viewport.*',
	'Ext.EventObject.*',
	'Ext.form.*',
	'Ext.data.*',
	'Ext.util.*',
	// 'Ext.ux.statusbar.StatusBar',
	'Ext.grid.*',
	'Ext.direct.*',
	'Ext.tab.*',
	'Ext.panel.*',
	'Ext.toolbar.*',
	'Ext.state.*',
	'Ext.button.*',
	'Ext.layout.container.Card',
	'Ext.layout.container.Border',
	'Ext.layout.container.Table',
	'Ext.ux.CheckColumn',
	'Ext.selection.CheckboxModel',
	'Ext.selection.CellModel'
]);

Ext.direct.Manager.addProvider(Ext.app.REMOTING_API);

// A global used to indicating paging switch in a 
// user list should not deselect all current page selected items.
var GRI_glob_portal_user_list_updating=0;
var GRI_glob_portal_report_list_updating=0;
var GRI_glob_portal_meta_reports_info={};
var griglobs_EMAIL_ADDR=undefined;

var cookie = new Ext.state.CookieProvider({
	path: "/",
	expires: null
	});
Ext.state.Manager.setProvider(cookie);

function grep(v,f) {
	for(i in v) {
		if(i==f) {
			return 1;
		}
	}
	return 0;
}

function get_parm(name) {
	name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
	var regexS = "[\\?&]"+name+"=([^&#]*)";
	var regex = new RegExp( regexS );
	var results = regex.exec(window.location.href);
	if(results == null) {
		return "";
	} else {
		return results[1];
	}
}

function setCookie(c_name,c_value) {
	return Ext.util.Cookies.set(c_name,c_value);
}

function clearExtCookies() {
	var L = [];
	var i,x,ARRcookies=document.cookie.split(";");
	for (i=0;i<ARRcookies.length;i++)
	{
		x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
		x=x.replace(/^\s+|\s+$/g,"");
		if(x.substr(0,4) == 'ext-') {
			L.push(x);
		}
	}
	for(i=0; i<L.length; i++) {
		console.log("Clearing cookie " + L[i]);
		Ext.util.Cookies.clear(L[i],'/');
	}
	return L;
}

function getCookie(c_name)
{
	return Ext.util.Cookies.get(c_name);
}

function getCookieElement(c_name,c_element)
{
	var cookie=getCookie(c_name);
	if(cookie == undefined) {
		return undefined;
	}

	// The cookie contents are in the format attribute=value&...
	var bits=cookie.split('&');
	for(var i=0; i<bits.length; i++) {
		if(bits[i] == c_element) {
			if(i+1<bits.length) {
				return bits[i+1];
			} else {
				return true;
			}
		}
	}
	return undefined;
}

function setCookieElement(c_name,c_element,c_value)
{
	var cookie=getCookie(c_name);
	if(cookie == undefined) {
		if(c_value == "" || c_value == undefined) {
			setCookie(c_name,c_element);
		} else {
			setCookie(c_name,c_element + "&" + c_value);
		}
		return;
	}

	// The cookie contents are in the format attribute=value&...
	var bits=cookie.split('&');
	var f=0;
	for(var i=0; i<bits.length; i++) {
		if(bits[i] == c_element) {
			if(i+1<bits.length) {
				bits[i+1]=c_value;
				f=1;
			} else {
				bits.push(c_value);
			}
		}
	}
	// Append if not found
	if(!f) {
		bits.push(c_element);
		bits.push(c_value);
	}
	var s=bits.join('&');
	setCookie(c_name,s);
}

function update_main_toolbar(state) {
var buts=[
	'refresh_button',
	'prefs_button',
	'recent_files_button',
	'alerts_button',
	'logout_button',
	'portals_filter_button'
	];

	for(r in buts) {
		var txt=buts[r];
		var gui_cmp=Ext.getCmp(txt);
		if(gui_cmp != undefined) {
			if(state==0) {
				gui_cmp.disable();
			} else {
				gui_cmp.enable();
			}
		}
	}
}

function set_admin_buttons(role_txt) {
	// Update the settings of the admin buttons based on user ID
	// and roles they have. Called from the login if login OK.

	var is_portal_admin=0;
	var is_report_admin=0;
	var is_user_admin=0;
	var my_roles_A=[];
	my_roles_A=role_txt.split(",");
	console.log("Roles:",my_roles_A);
	for(var i=0; i<my_roles_A.length; i++) {
		if(my_roles_A[i]=="portal_admin") {
			is_portal_admin=1;
		}
		if(my_roles_A[i]=="report_admin") {
			is_report_admin=1;
		}
		if(my_roles_A[i]=="user_admin") {
			is_user_admin=1;
		}
	}
	var gui_cmp=Ext.getCmp('user_admin_button');
	if(gui_cmp != undefined) {
		console.log("user admin:", is_user_admin);
		if(is_user_admin) {
			gui_cmp.enable();
		} else {
			gui_cmp.disable();
		}
	}
	gui_cmp=Ext.getCmp('report_admin_button');
	if(gui_cmp != undefined) {
		console.log("report admin:", is_report_admin);
		if(is_report_admin) {
			gui_cmp.enable();
		} else {
			gui_cmp.disable();
		}
	}
	gui_cmp=Ext.getCmp('portal_admin_button');
	if(gui_cmp != undefined) {
		console.log("portal admin:", is_portal_admin);
		if(is_portal_admin) {
			gui_cmp.enable();
		} else {
			gui_cmp.disable();
		}
	}
}

function main_layout() {
	// In the top panel we would put heading information
	// In the middle panel table for reports
	// In the third panel document repository
	// In the forth panel there is updates/news etc...
	// var header_panel=toplevel.query('#header_panel');
	// var portals_panel=toplevel.query('#portals_panel');

	var is_portal_admin=0;
	var is_report_admin=0;
	var is_user_admin=0;
	var my_roles=getCookieElement("GRI2_prefs","ROLES");
	var my_roles_A=[];
	if(my_roles != undefined) {
		my_roles_A=my_roles.split(",");
		console.log("Roles:",my_roles_A);
		for(var i=0; i<my_roles_A.length; i++) {
			if(my_roles_A[i]=="portal_admin") {
				is_portal_admin=1;
			}
			if(my_roles_A[i]=="report_admin") {
				is_report_admin=1;
			}
			if(my_roles_A[i]=="user_admin") {
				is_user_admin=1;
			}
		}
	}

	Ext.create('Ext.data.ArrayStore', {
		storeId: 'portals_grid',
		fields: [
			{name: 'pname'},
			{name: 'fname'},
			{name: 'pactions'},
			{name: 'padmin'},
			{name: 'reports'},
			{name: 'rcount'},
			{name: 'mreports'},
			{name: 'mrcount'},
			{name: 'users'},
			{name: 'ucount'},
			{name: 'raw_xml'}
		],
		data: [ ]
	});

	// Same as the above, but used for admin listing
	// all portals...
	Ext.create('Ext.data.ArrayStore', {
		storeId: 'all_portals_grid',
		fields: [
			{name: 'name'},
			{name: 'fname'},
			{name: 'pactions'},
			{name: 'padmin'},
			{name: 'reports'},
			{name: 'rcount'},
			{name: 'mreports'},
			{name: 'mrcount'},
			{name: 'users'},
			{name: 'ucount'},
			{name: 'rawxml'}
		],
		data: [ ]
	});

	Ext.create('Ext.data.ArrayStore', {
		storeId: 'user_list_selection',
		idIndex: 0,
		fields: [
			{name: 'uid'},
			{name: 'included'},
		],
		data: [ ]
	});
	Ext.create('Ext.data.ArrayStore', {
		storeId: 'report_list_selection',
		idIndex: 0,
		fields: [
			{name: 'rfile'},
			{name: 'selected'},
			{name: 'filename'},
			{name: 'reptype'},
		],
		data: [ ]
	});
	Ext.create('Ext.data.ArrayStore', {
		storeId: 'recent_files_list',
		idIndex: 0,
		fields: [
			{name: 'file'},
			{name: 'name'},
			{name: 'size'},
			{name: 'date'},
			{name: 'mtime'},
			{name: 'type'},
			{name: 'portal'}
		],
		data: [ ]
	});
	Ext.create('Ext.data.ArrayStore', {
		storeId: 'alerting_panel',
		idIndex: 0,
		fields: [
			{name: 'name'},
			{name: 'portal'},
			{name: 'text'},
			{name: 'alerting', type: 'bool'},
			{name: 'error'},
			{name: 'value'}
		],
		data: []
	});
	var portals_grid_store=Ext.data.StoreManager.lookup('portals_grid');
	var _username;
	if(window.griglobs_ATTEMPTED_LOGIN_AS !== undefined) {
		_username=window.griglobs_ATTEMPTED_LOGIN_AS;
	} else {
		_username=cookie.get('login','?Unknown?');
	}
	var portals_grid=Ext.create('Ext.grid.Panel', {
		// verticalScrollerType: 'paginggridscroller',
		store: portals_grid_store,
		stateful: false,
		id: 'portal_section_grid',
		// layout:'anchor',
		// anchor:'100% 50%',
		// layout: 'fit',
		tbar: [{
			// height: 32,
			// width: 32,
			icon: 'resources/images/filter.gif',
			text: 'Filter',
			iconAlign: 'top',
			id: 'portals_filter_button',
			tooltip: 'Filter Results',
			listeners: {
				click: function() {
					var ds=Ext.data.StoreManager.lookup('portals_grid');
					var show_pl_all = cookie.get("show_pl_all","!!NOT_SET!!");
					if(show_pl_all == "!!NOT_SET!!" || show_pl_all == "0") {
						cookie.set('show_pl_all','1');
						ds.clearFilter();
					} else {
						cookie.set('show_pl_all','0');
						ds.filter('pactions','1');
					}
				}
			}
		}],
		columns: [
			{
				text: 'Portal Name',
				flex: 4,
				sortable: true,
				dataIndex: 'pname'
			},{
				text: 'User #',
				flex: 1,
				sortable: true,
				dataIndex: 'ucount',
				hidden: true,
			},{
				text: 'Report #',
				flex: 1,
				sortable: true,
				dataIndex: 'rcount',
				hidden: true,
			},{
				xtype: 'actioncolumn',
				text: 'Actions',
				// dataIndex: 'pactions'
				flex: 1,
				sortable: false,
				items: [{
					// icon: 'resources/images/small_folder.png',
					// tooltip: 'View Portal',
					disabled: false,
					handler: function(grid, rowIndex, colIndex) {
						var rec = portals_grid_store.getAt(rowIndex);
						if(rec.get('pactions')=="0") {
							request_portal_access_form(rec.get('pname'));
						} else {
							view_available_portals_window(rec.get('pname'));
						}
					},
					getClass: function(v, meta, rec, rowIndex, colIndex, store) {
						if(rec.get('pactions')=="0") {
							this.items[0].tooltip = 'Request Access';
							return "portalRequestAccessIcon";
						}
						this.items[0].tooltip = 'View Portal';
						return "portalAccessIcon";
					}
				},{
					// icon: 'resources/images/small_folder.png',
					// tooltip: 'View Portal',
					disabled: false,
					handler: function(grid, rowIndex, colIndex) {
						var rec = portals_grid_store.getAt(rowIndex);
						edit_portal_window(rec.get('pname'),"Edit Portal Details");
					},
					getClass: function(v, meta, rec, rowIndex, colIndex, store) {
						this.items[1].tooltip = 'View Portal Settings';
						if(rec.get('padmin')=="1") {
							this.items[1].tooltip = 'Edit Portal Settings';
						}
						return "portalAdminIcon";
					}
				},{
					// icon: 'resources/images/small_mark_link.png',
					// tooltip: xml_tooltip,
					disabled: false,
					handler: function(grid, rowIndex, colIndex) {
						var rec = portals_grid_store.getAt(rowIndex);
						view_available_portal_config(rec,is_portal_admin);
					},
					getClass: function(v, meta, rec, rowIndex, colIndex, store) {
						this.items[2].tooltip = 'View Raw Portal XML';
						if(rec.get('padmin')=="1" || is_portal_admin) {
							this.items[2].tooltip = 'View/Edit Raw Portal XML';
						} else {
							this.items[2].tooltip = 'View Raw Portal XML';
						}
						return "portalXmlIcon";
					}
				}]
			},
		],
		title: 'Available Portals for ' + _username,
		viewConfig: {
			stripeRows: true,
			trackOver: false
		}
	});
	var toplevel = Ext.create('Ext.Viewport', {
		layout: 'border',
		id: 'toplevel_viewport',
		items: [{
			region:'north',
			layout:'fit',
			margins: '5 5 5 5',
			// height: 85,
			items: [ {
				xtype: 'panel',
				title: 'GRI2 Toolbar + Actions',
				scale: 'large',
				tbar: [{
					// height: 64,
					// width: 50,
					icon: 'resources/images/refresh.gif',
					iconAlign: 'top',
					id: 'refresh_button',
					text: 'Refresh',
					textAlign: 'bottom',
					tooltip: 'Refresh Window Contents',
					cls: 'x-btn-text-icon',
					listeners: {
						click: function() {
							this.disable();
							populate_toplevel(login_user_name);
							this.enable();
						}
					}
				}, {
					// height: 64,
					// width: 50,
					icon: 'resources/images/preferences.gif',
					iconAlign: 'top',
					text: 'Prefs',
					id: 'prefs_button',
					textAlign: 'bottom',
					tooltip: 'Update Preferences',
					disabled: false,
					cls: 'x-btn-text-icon',
					listeners: {
						click: function() {
							Remote_Actions.get_all_preference_data(
								function(provider,response) {
									show_prefs_window(response.result);
								}
							);
						}
					}
				}, {
					// height: 64,
					// width: 50,
					icon: 'resources/images/recent.gif',
					iconAlign: 'top',
					text: 'Recent',
					id: 'recent_files_button',
					textAlign: 'bottom',
					tooltip: 'Show/Hide Recent Files Window',
					disabled: false,
					cls: 'x-btn-text-icon',
					listeners: {
						click: function() {
							this.disable();
							toggle_rfw();
							this.enable();
						}
					}
				}, {
					// height: 64,
					// width: 50,
					icon: 'resources/images/alerting.gif',
					iconAlign: 'top',
					text: 'Alerting',
					id: 'alerts_button',
					textAlign: 'bottom',
					tooltip: 'Manage Your Alerts',
					disabled: false,
					cls: 'x-btn-text-icon',
					listeners: {
						click: function() {
							this.disable();
							handle_alerts();
							this.enable();
						}
					}
				},'-', {
					// height: 64,
					// width: 50,
					icon: 'resources/images/user_admin.gif',
					iconAlign: 'top',
					text: 'User Admin',
					id: 'user_admin_button',
					textAlign: 'bottom',
					tooltip: 'Manage Users',
					disabled: true,
					cls: 'x-btn-text-icon',
					listeners: {
						click: function() {
							this.disable();
							// handle_alerts();
							this.enable();
						}
					}
				}, {
					// height: 64,
					// width: 50,
					icon: 'resources/images/report_admin.gif',
					iconAlign: 'top',
					text: 'Report Admin',
					id: 'report_admin_button',
					textAlign: 'bottom',
					tooltip: 'Manage Reports',
					disabled: true,
					cls: 'x-btn-text-icon',
					listeners: {
						click: function() {
							this.disable();
							reports_admin();
							this.enable();
						}
					}
				}, {
					// height: 64,
					// width: 50,
					icon: 'resources/images/portal_admin.gif',
					iconAlign: 'top',
					text: 'Portal Admin',
					id: 'portal_admin_button',
					textAlign: 'bottom',
					tooltip: 'Manage Portals',
					disabled: true,
					cls: 'x-btn-text-icon',
					listeners: {
						click: function() {
							this.disable();
							portals_admin();
							this.enable();
						}
					}
				},'->', {
					// height: 64,
					// width: 50,
					icon: 'resources/images/logout.gif',
					iconAlign: 'top',
					text: 'Logout',
					id: 'logout_button',
					textAlign: 'bottom',
					disabled: true,
					// cls: 'x-btn-text-icon'
					listeners: {
						click: function() {
							clear_status_text();
							Remote_Actions.logout(
								function(provider,response) {
									var ps = Ext.data.StoreManager.lookup('portals_grid');
									var pan=Ext.getCmp('portal_section_grid');
									pan.setTitle('');
									ps.removeAll();
									cookie.clear("login");
									destroy_recent_files_window();
									update_main_toolbar(0); // disable it
									set_admin_buttons('');
									login_window();
								}
							);
						}
					}
				}]
			} ]
		}, {
			region:'center',
			margins: '5 5 5 5',
			layout: 'fit',
			items: portals_grid
		}, {
			region:'south',
			margins: '5 5 5 5',
			layout:'fit',
			items: [ {
				xtype: 'panel',
				title: 'Status Bar',
				height: 120,
				layout: {
					type: 'vbox',
					align: 'stretch'
				},
				items: [{
					xtype: 'textarea',
					id: 'status_bar',
					name: 'status_bar',
					text: 'Ready',
					readOnly: true,
					padding: 0,
					flex: 1
				}]
			} ]
		}]
	});
	var statusbar = Ext.getCmp("status_bar");
	return(toplevel,statusbar);
}

function myRT2(v,meta,rec) {
	// If we are a normal report
	var reptype=rec.get('reptype');
	if(reptype != 'M') {
		return rec.get('rtype');
	}
	return "META - " + rec.get('rtype');
}

function myCB2(v) {
	if(v) {
		return "<font color=red>Yes</font>";
	}
	return "No";
}

function myCB(v) {
	if(v) {
		return "<font color=red>On</font>";
	}
	return "Off";
}

function handle_alerts() {

	var ds=Ext.data.StoreManager.lookup('alerting_panel');
	ds.removeAll();

	// Pop up a window and then define a grid panel using the ds store

	var h =  this.innerHeight;
	var w = this.innerWidth;
	var cellEditing = Ext.create('Ext.grid.plugin.CellEditing', {
		clickstoEdit: 1
	});
	var alerting_view_window = Ext.create('Ext.Window', {
		title: 'Alerting Configuration',
		width: w-2,
		height: h-2, 
		x: 1,
		y: 1,
		id: 'alertingWindow',
		modal: true,
		renderTo: document.body,
		headerPosition: 'top',
		layout: 'anchor',
		items: [{
			id: 'alerting_grid',
			anchor: '100% 100%',
			xtype: 'grid',
			store: ds,
			viewConfig: {
				stripeRows: true,
				trackOver: false
			},
			columns: [
				{header: 'Report', flex:3, dataIndex: 'text'},
				{header: 'Portal', flex:3, dataIndex: 'portal'},
				{header: 'Alerting', width:50, dataIndex: 'alerting',
					xtype: 'checkcolumn', renderer: myCB}
			]
		}],
		bbar: [
			{ xtype: 'button', text: 'Cancel',
				listeners: {
					click: function() {
						this.up('window').close();
					}
				}
			},
			'->',
			{ xtype: 'button', text: 'Save',
				listeners: {
					click: function() {
						this.up('panel').setLoading('Updating ...');
						// dump all values for store...
						var my_alerts=[];
						for(var x=0; x<ds.count(); x++) {
							// Gather those records which are now true...
							var c_rec=ds.getAt(x);
							var alerting_on=c_rec.get('alerting');
							if(alerting_on==true) {
								var nn=c_rec.get('name');
								var pp=c_rec.get('portal');
								my_alerts.push( {
									name: nn,
									portal: pp
								});
							}
						}
						console.log(my_alerts);	
						console.log('Total enabled alerts: ' + my_alerts.length);
						var my_win=this.up('window');
						Remote_Actions.set_user_alerting_info(my_alerts,undefined,
								function(provider,response) {
									var res=response.result;
									my_win.close();
									if(res.error != undefined) {
										my_alert(res.error,'E',"Failed to update alerting info");
									} else {
										append_status_text("User alerting information updated.");
									}
								}
						);
					}
				}
			}
		]
	});
	alerting_view_window.show();
	var gid=Ext.getCmp('alerting_grid');
	gid.setLoading('Retrieving ...');

	Remote_Actions.get_user_alerting_info(
		function(provider,response) {
			var res=response.result;
			console.log(res);
			if(res.error != undefined) {
				append_status_text(res.error);
				return;
			}
			for(crep in res) {
				if(res[crep].text == undefined) {
					var v=res[crep].value;
					v=v.substr(0,v.indexOf('~'));
					res[crep].text=v;
				}
				ds.add(res[crep]);
				console.log(res[crep]);
			}
			console.log("Store count:" + ds.count());
			var gid=Ext.getCmp('alerting_grid');
			gid.setLoading(false);
		}
	);
}

function update_recent_files_window(this_win,mystore) {
	var max_count=getCookieElement("GRI2_prefs","recent_files_pane_count");
	if(max_count == undefined) {
		max_count=10;
	}
	var max_age=getCookieElement("GRI2_prefs","recent_files_oldest");
	if(max_age == undefined) {
		max_age=72;
	}
	// this_win.show();
	this_win.setLoading("Retrieving...");
	mystore.removeAll();
	Remote_Actions.get_latest_updated_reports(max_count,max_age,
		function(provider,response) {
			var res=response.result;
			if(res.error != undefined) {
				append_status_text(res.error);
				this_win.setLoading(false);
				this_win.destroy();
				return;
			}
			// res.reports is an array of objects
			var i=res.reports.length;
			for(var l=0; l<i; l++) {
				mystore.add({
					file: res.reports[l].file,
					name: res.reports[l].name,
					portal: res.reports[l].portal,
					date: res.reports[l].date,
					mtime: res.reports[l].mtime,
					size: res.reports[l].size,
					type: res.reports[l].type
				});
			}
			this_win.setLoading(false);
		}
	);
}

function destroy_recent_files_window() {
	var this_win = Ext.getCmp("recent_files_window");
	if(this_win != undefined) {
		this_win.destroy();
	}
}

function show_prefs_window(res) {

	var vp=Ext.getCmp('toplevel_viewport');
	vp.setLoading('Getting Details ...');
	if(res.error != undefined) {
		alert('Failed during preference retrieval: ' + res.error,'E','Preferences Error');
		return;
	}
	// We show a window of all preferece options
	// res.prefs is an object where preference name is attribute
	// and each consists of an array with upto 5 elements:
	// 0 - Text Description
	// 1 - base64 encoded current value
	// 2 - minimum value (if numeric)
	// 3 - maximum value (if numeric)
	// 4 - pipe separated options (if options list)

	// Notice the number of preference changes so the output
	// should be as dynamic as possible.
	// table of 2 columns: Description, value entry.

	var this_win = Ext.create('Ext.window.Window', {
		title: 'User Preferences',
		height: 500,
		modal: true,
		width: 600,
		id: 'user_prefs_window',
		layout: 'vbox',
		// layout: 'fit',
		bbar: [
			{	xtype: 'button', text: 'Cancel',
				listeners: {
					click: function() {
						this_win.close();
					}
			} },
			'->',
			{	xtype: 'button', text: 'Save',
				id: 'prefs_ok_button'
			},
		],
		minimizable: false
	});

	var A=[];
	for(cobj in res.prefs) {
		// Create a container (hbox layout with text and textfield...
		console.log(res.prefs[cobj]);
		var c_value=base64_decode(res.prefs[cobj][1]);
		var c_min=res.prefs[cobj][2];
		var c_max=res.prefs[cobj][3];
		if(res.prefs[cobj][4] != "") {
			var c_options=res.prefs[cobj][4].split('|');
			// Combo options list to show...
			A.push(
				{
					xtype: 'container',
					layout: 'hbox',
					width: 550,
					height: 50,
					border: 1,
					defaults: {
						flex: 1,
						style: {
							padding: '10px'
						}
					},
					items: [
						{text: res.prefs[cobj][0], xtype: 'label', width: 200},
						{xtype: 'combo', name: cobj, width: 200,
							value: c_value, store: c_options, forceSelection: true}
					]
				}
			);
			continue;
		}
		if(c_min=="" && c_max=="") {
			// free form text 
			A.push(
				{
					xtype: 'container',
					layout: 'hbox',
					width: 550,
					height: 50,
					border: 1,
					defaults: {
						flex: 1,
						style: {
							padding: '10px'
						}
					},
					items: [
						{text: res.prefs[cobj][0], xtype: 'label', width: 200},
						{xtype: 'textfield', name: cobj, width: 200, value: c_value}
					]
				}
			);
			continue;
		}
		if(true) {
			// If min/max are given then this item is a spinner.
			console.log("max: " + c_max + " min: " + c_min);
			A.push(
				{
					xtype: 'container',
					layout: 'hbox',
					width: 550,
					height: 50,
					border: 1,
					defaults: {
						flex: 1,
						style: {
							padding: '10px'
						}
					},
					items: [
						{text: res.prefs[cobj][0], xtype: 'label', width: 200},
						{xtype: 'numberfield', name: cobj, width: 200, 
							minValue: c_min, maxValue: c_max, value: c_value}
					]
				}
			);
		}
	}
	this_win.add(A);
	var but = Ext.getCmp('prefs_ok_button');
	if(but != undefined) {
		but.on('click',function() {
			// We know the names of all fields now, 
			// so should be able to extract them and their
			// current values - and compare them to the original
			// before submitting change.
			var fields = this_win.query('field');
			var updates = {};
			var updated = 0;
			var s="";
			for(var c=0; c<fields.length; c++) {
				var fname=fields[c].name;
				var cvalue=fields[c].value;
				var evalue=base64_decode(res.prefs[fname][1]);
				if(cvalue != evalue) {
					updates[fname]=cvalue;
					updated++;
					setCookieElement("GRI2_prefs",fname,cvalue);
				}
				if(s=="") {
					; //?
				} else {
					; //?
				}
			}
			if(updated) {
				// Some preferences are updated, so call
				// the remote update code
				Remote_Actions.set_preference_data(updates,
					function(provider,response) {
						var mm=response.result;
						console.log(mm);
					}
				);
				// we also update the preferences in the GRI2_prefs
				// cookie for code to pick up immediately.
			}
			this_win.close();
		});
	} else {
		console.log("Unable to find button!!");
	}
	vp.setLoading(false);
	this_win.show();
	// Window is a continue so should be able to 
}

function toggle_rfw() {
	var this_win = Ext.getCmp("recent_files_window");
	if(this_win == undefined) {
		show_recent_files_window();
	} else {
		if(this_win.isHidden()) {
			this_win.show();
		} else {
			this_win.hide();
		}
	}
}

function show_recent_files_window() {
	var recent_files_store=Ext.data.StoreManager.lookup('recent_files_list');
	recent_files_store.removeAll();
	var this_win = Ext.create('Ext.window.Window', {
		title: 'Recently Updated Files',
		height: 200,
		width: 600,
		id: 'recent_files_window',
		layout: 'fit',
		minimizable: false,
		tbar: [{
			// height: 32,
			// width: 32,
			// text: 'Refresh',
			icon: 'resources/images/refresh.gif',
			iconAlign: 'top',
			id: 'latest_reports_filter_button',
			tooltip: 'Refresh Results',
			listeners: {
				click: function() {
					update_recent_files_window(this_win,recent_files_store);
				}
			}
		}],
		items: {
			xtype: 'grid',
			border: false,
			store: recent_files_store,
			columns: [
				{header: 'Report Name', dataIndex: 'name', sortable: true, flex: 2 },
				{header: 'Portal', dataIndex: 'portal', sortable: true, flex: 3},
				{header: 'Date', dataIndex: 'date', sortable: true, flex: 1},
				{xtype: 'actioncolumn', flex:1, sortable: false,
					text: 'Actions',
					items: [{
						icon: 'resources/images/access.gif',
						tooltip: 'View Report',
						disabled: false,
						handler: function(grid, rowIndex, colIndex) {
							var r = recent_files_store.getAt(rowIndex);
							populate_window(r.get('portal'),r.get('file'),r.get('mtime'),"R",r.get('date'));
						}
					}]}
			]
		}
	});
	this_win.show();
	this_win.setLoading("Retrieving...");
	var max_count=getCookieElement("GRI2_prefs","recent_files_pane_count");
	if(max_count == undefined) {
		max_count=10;
	}
	var max_age=getCookieElement("GRI2_prefs","recent_files_oldest");
	if(max_age == undefined) {
		max_age=72;
	}
	Remote_Actions.get_latest_updated_reports(max_count,max_age,
		function(provider,response) {
			var res=response.result;
			if(res.error != undefined) {
				append_status_text(res.error);
				this_win.setLoading(false);
				this_win.destroy();
				return;
			}
			// res.reports is an array of objects
			var i=res.reports.length;
			for(var l=0; l<i; l++) {
				recent_files_store.add({
					file: res.reports[l].file,
					name: res.reports[l].name,
					portal: res.reports[l].portal,
					date: res.reports[l].date,
					mtime: res.reports[l].mtime,
					size: res.reports[l].size,
					type: res.reports[l].type
				});
				// console.log("Adding:");
				// console.log(res.reports[l]);
			}
			this_win.setLoading(false);
			var update_latest_files_window_task=function() {
				var this_win = Ext.getCmp("recent_files_window");
				var recent_files_store=Ext.data.StoreManager.lookup('recent_files_list');
				if(this_win != undefined) {
					update_recent_files_window(this_win,recent_files_store);
				}
			}
			var task = {
				run: update_latest_files_window_task,
				interval: 300000 // 300 seconds (5 mins)
			}
			var runner = new Ext.util.TaskRunner();
			runner.start(task);
		}
	);
}

function clear_status_text() {
	var statusbar = Ext.getCmp("status_bar");
	statusbar.setValue('');
}

function append_status_text(txt) {
	var statusbar = Ext.getCmp("status_bar");
	var str = statusbar.getValue();
	if(str.length>0) {
		str=str + "\n" + txt
	} else {
		str = txt
	}
	statusbar.readOnly=false;
	statusbar.setValue(str);
	var txtarea = statusbar.getEl();
	txtarea.scrollTop = txtarea.scrollHeight;
	statusbar.readOnly=true;
}

function populate_toplevel(user,dl_portal,dl_report,dl_rep_mtime) {
	var psg = Ext.getCmp("portal_section_grid");
	if(psg != undefined) {
		var cv2 = getCookie('GRI2SD');
		if(cv2 != undefined) {
			Ext.util.Cookies.clear('GRI2SD','/');
			if(cv2=="alerts") {
				action="Show Alerts";
				handle_alerts();
			}
			if(cv2=="prefs") {
				action="Show Preferences";
				Remote_Actions.get_all_preference_data(
					function(provider,response) {
						show_prefs_window(response.result);
					}
				);
			}

		}
		psg.setTitle('Available Portals for ' + user);
		Remote_Actions.map_uids([user],
			function(provider,response) {
				var res=response.result;
				for(uid in res.uids) {
					psg.setTitle('Available Portals for ' + res.uids[uid].name);
					griglobs_EMAIL_ADDR=res.uids[uid].email;
				}
			}
		);
		psg.setLoading("Retrieving...");
		Remote_Actions.get_user_portal_list(
			function(provider,response) {
				psg.disable();
				var res=response.result;
				if(res.error != undefined) {
					if(res.error.indexOf("Invalid user access for")>-1) {
						return false;
					}
					append_status_text(res.error);
					return true;
				}
				// Get the store and populate the details (portal,name,rcount,users,admin)
				var ds=Ext.data.StoreManager.lookup('portals_grid');
				ds.removeAll();
				var arLen=res.repinfo.length;
				for(var i=0,len=arLen; i<len; ++i) {
					ds.add({
						pname: res.repinfo[i].name,
						pactions: res.repinfo[i].access,
						rcount: res.repinfo[i].rcount,
						reports: res.repinfo[i].reports,
						users: res.repinfo[i].users,
						ucount: res.repinfo[i].ucount,
						padmin: res.repinfo[i].admin,
						raw_xml: base64_decode(res.repinfo[i].rawxml),
					});
				}

				var show_pl_all = cookie.get("show_pl_all","!!NOT_SET!!");
				if(show_pl_all == "!!NOT_SET!!" || show_pl_all == "0") {
					ds.filter('pactions','1');
				} else {
					ds.clearFilter();
				}
				Remote_Actions.get_roles(
					function(provider,response2) {
						var res2=response2.result;
						if(res2.error != undefined) {
							append_status_text(res2.error);
						} else {
							setCookieElement("GRI2_prefs","ROLES",res2.roles.join(","));
							set_admin_buttons(res2.roles.join(","));
						}
						if(dl_portal !== undefined) {
							console.log("HERE - viewing report info!");
							view_available_portals_window(dl_portal,dl_report,dl_rep_mtime);
						}
						// psg.showVerticalScroller();
						psg.setLoading(false);
						psg.enable();
					}
				);
		
				// console.log("Count of elements in datastore:" + ds.count());
				// statusbar.setValue('');
			}
		);
		var lb = Ext.getCmp("logout_button");
		if(window.griglobs_ALLOW_LOGOUT == undefined ||
			window.griglobs_ALLOW_LOGOUT == 1) {
			lb.enable();
		}		
	}
	return true;
}

function login_error(t) {

	var msg="Specified details are incorrect.";
	if(t!=undefined && t.length>0) {
		msg=t;
	}
	if(t == "NO_AUTHD") {
		msg="No authentication daemon is running - please contact Administrator.";
	}
	my_alert(msg,'E',"Login Error"); 
}

function check_login(obj,thisform,dl_portal,dl_report,dl_rep_mtime) {
	console.log("check_login: dl_portal,dl_report,dl_rep_mtime:");
	console.log(dl_portal);
	console.log(dl_report);
	console.log(dl_rep_mtime);
	Remote_Actions.login(obj.user, obj.password,
		function(provider,response) {
			var res=response.result;
			if(res.error == undefined && res.result == undefined) {
				login_error("NO_AUTHD");
				if(thisform != undefined) {
					var f=thisform.getForm();
					f.reset();
					thisform.enable();
				} else {
					obj.fuser.reset();
					obj.fpass.reset();
				}
				return;
			}
			if(res.error != undefined) {
				login_error(res.error);
				if(thisform != undefined) {
					var f=thisform.getForm();
					f.reset();
					thisform.enable();
				} else {
					obj.fuser.reset();
					obj.fpass.reset();
				}
				return;
			}
			var loginWindow = Ext.getCmp('loginWindow');
			if(res.result == "OK") {
				login_user_name=obj.user;
				loginWindow.hide();
				loginWindow.destroy();
				cookie.set("login",login_user_name,-1);

				// Show the portals available for this user
				populate_toplevel(login_user_name,dl_portal,dl_report,dl_rep_mtime);
				update_main_toolbar(1);

				// Work out whether so show recent reports pane by default
				var show_pane=getCookieElement("GRI2_prefs","recent_files_pane");
				if(show_pane==undefined) {
					show_pane=false;
				} else {
					show_pane=eval(show_pane);
				}
				if(show_pane==true) {
					show_recent_files_window();
				}
			} else {
				login_error(res.result);
				if(thisform != undefined) {
					var f=thisform.getForm();
					f.reset();
					thisform.enable();
				} else {
					obj.fuser.reset();
					obj.fpass.reset();
				}
			}
		}
	);
}

function login_window(dl_portal,dl_report,dl_rep_mtime) {

	if(window.griglobs_ATTEMPTED_LOGIN_AS !== undefined) {
		// SSO indicates we should be this user...
		login_user_name=window.griglobs_ATTEMPTED_LOGIN_AS;
		var ok_login=populate_toplevel(login_user_name,dl_portal,dl_report,dl_rep_mtime);
		if(ok_login==false) {
			update_main_toolbar(0);
			login_window(dl_portal,dl_report,dl_rep_mtime);
		}
		cookie.set("login",login_user_name,-1);
		// if(dl_portal !== undefined) {
			// view_available_portals_window(dl_portal,dl_report,dl_rep_mtime);
			// return;
		// }
		var show_pane=getCookieElement("GRI2_prefs","recent_files_pane");
		if(show_pane==undefined) {
			show_pane=false;
		} else {
			show_pane=eval(show_pane);
		}
		if(show_pane==true) {
			show_recent_files_window();
		}
		update_main_toolbar(1);
		return;
	}
	// cookie.clear("login");
	var txt=""; var abt=""; var abt_link="";
	if(window.griglobs_LOGIN_WARNING_TXT !== undefined) {
		txt=griglobs_LOGIN_WARNING_TXT;
	}
	var abt_a=[];
	if(window.griglobs_LOGIN_ABOUT_TXT !== undefined) {
		abt=griglobs_LOGIN_ABOUT_TXT;
		abt_link=griglobs_LOGIN_ABOUT_LNK;
		abt_a.push({
				xtype: 'label',
				html: "<br><br>" + abt + "&nbsp;&nbsp;",
				margins: '10 10 10 10'
			});
		abt_a.push({
				xtype: 'button',
				text: 'More...',
				href: abt_link
			});
	}
	var login_window = Ext.create('Ext.window.Window', {
		id: 'loginWindow',
                // anchor: '100% 100%',
				width: 400,
				height: 400,
                layout: {
                    type: 'vbox',
                    align: 'stretch'
                },
                border: false,
                bodyPadding: 10,
                fieldDefaults: {
                    labelAlign: 'left',
                    labelWidth: 100,
                    labelStyle: 'font-weight:bold'
                },
                defaults: {
                    margins: '0 0 10 0'
                },
                items: [
				{
					xtype: 'box',
					html: "<img src=\"" + griglobs_MIDDLE_HEADER_LOGO + "\"/>",
					height: 50
				}, {
					xtype: 'label',
					// xtype: 'tbtext',
					text: "Please enter your authentication details for \"" + griglobs_AUTH_HOST + "\"",
					margins: '10 10 10 10'
				}, {
					// width: 30,
					id: 'loginUsername',
					xtype: 'textfield',
					name: 'user',
					fieldLabel: 'Username',
					allowBlank: false
                }, {
					// width: 30,
					id: 'loginPassword',
					xtype: 'textfield',
					name: 'password',
					inputType: 'password',
					fieldLabel: 'Password',
				}, {
					xtype: 'label',
					text: txt,
					margins: '10 10 10 10'
                },
				abt_a],
		buttons: [{
			text: 'Clear Form',
			handler: function() {
				var x=Ext.getCmp('loginPassword');
				x.reset();
				x=Ext.getCmp('loginUsername');
				x.reset();
			}
		    }, { xtype: 'tbfill' }, {
			text: 'Login',
			handler: function() {
				var thisform = Ext.getCmp('loginWindow');
				var obj = {}
				obj.fuser = userentry;
				obj.fpass = passentry;
				obj.user = Ext.getCmp('loginUsername').getValue()
				obj.password = Ext.getCmp('loginPassword').getValue()
				append_status_text("Loading Portal information ...");
				check_login(obj,undefined,dl_portal,dl_report,dl_rep_mtime);
			}
		}]
	});

	// keymapping stuff is added via an event since it works on an El and the
	// el is only available after rendering is complete!
	var userentry = Ext.getCmp('loginUsername');
	var passentry = Ext.getCmp('loginPassword');
	passentry.addListener('afterrender',function() {
		userentry.focus();
		var xx2=this.getEl();
		var map = new Ext.util.KeyMap(xx2,{
				key: 13, // Ext.EventObject.ENTER,
				fn: function() {
						var thisform = Ext.getCmp('loginWindow');
						var obj = {}
						obj.fuser = userentry;
						obj.fpass = passentry;
						obj.user = Ext.getCmp('loginUsername').getValue()
						obj.password = Ext.getCmp('loginPassword').getValue()
						append_status_text("Loading Portal information ...");
						check_login(obj,undefined,dl_portal,dl_report,dl_rep_mtime);
				}
		});
	});

	var user_id = cookie.get("login","!!NOT_SET!!");
	console.log("user_id:" + user_id);
	if(user_id == "!!NOT_SET!!") {
		// Get rid of all ext- cookies to ensure we start fresh..
		clearExtCookies();
		update_main_toolbar(0);
		login_window.show();
	} else {
		login_user_name=user_id;
		update_main_toolbar(1);
		var ok_login=populate_toplevel(login_user_name,dl_portal,dl_report,dl_rep_mtime);
		if(ok_login==false) {
			update_main_toolbar(0);
			login_window(dl_portal,dl_report,dl_rep_mtime);
			return;
		}
		// if(dl_portal !== undefined) {
			// view_available_portals_window(dl_portal,dl_report,dl_rep_mtime);
			// return;
		// }
		var show_pane=getCookieElement("GRI2_prefs","recent_files_pane");
		if(show_pane==undefined) {
			show_pane=false;
		} else {
			show_pane=eval(show_pane);
		}
		if(show_pane==true) {
			show_recent_files_window();
		}
		update_main_toolbar(1);
	}
}

// View portal configuration as xml
// rec is a record with the following fields:
// {name: 'pname'},
// {name: 'fname'},
// {name: 'pactions'},
// {name: 'padmin'},
// {name: 'reports'},
// {name: 'rcount'},
// {name: 'users'},
// {name: 'ucount'}
// {name: 'raw_xml'}

function view_available_portal_config(rec,is_portal_admin,data_store) {
	console.log(rec);
	var portal_xml = rec.get('raw_xml');
	if(portal_xml == undefined || portal_xml.length==0) {
		var portal_xml = rec.get('rawxml');
	}
	console.log(portal_xml);
	var portal_name = rec.get('pname');
	if(portal_name == undefined) {
		portal_name = rec.get('name');
	}
	var portal_fname = rec.get('fname');

	var h =  this.innerHeight;
	var w = this.innerWidth;

	if(rec.get('padmin')=="1") {
		is_portal_admin=1;
	}
	var bbar_data=[];
	if(is_portal_admin) {
		var bbar_data=[{
					xtype: 'button', text: 'Cancel',
						listeners: {
							click: function() {
								this.up('window').close();
							}
						}
					}, '->',
					{
					xtype: 'button', text: 'Save',
						listeners: {
							click: function() {
								var my_panel=this.up('panel');
								my_panel.setLoading('Updating ...');
								// dump all values for store...
								var myentry = Ext.getCmp('dummy_field2_for_rawxml');
								var xml_info=myentry.getValue();
								Remote_Actions.set_portal_xml(portal_name,xml_info,
										function(provider,response) {
											var res=response.result;
											console.log("parse_result:",res);
											if(res.validated != undefined) {
												my_alert(res.validated,'E',"Invalid XML detected.");
												my_panel.setLoading(false);
											} else if(res.error != undefined) {
												my_alert(res.error,'E',"Failed to update report XML");
												my_panel.setLoading(false);
											} else {
												var my_win = Ext.getCmp('portal_rawxml');
												append_status_text("XML updated as requested.");
												// Need to update the value in the store as well....
												rec.set('raw_xml',xml_info);
												my_win.close();
												// If we have saved and the data must be
												// considered to have changed so reload 
												// the store if available.
												if(data_store !== undefined) {
													data_store.load();
												}
											}
										}
								);
							}
						}
				}];
	} else {
		bbar_data=[{
					xtype: 'button', text: 'Close',
						listeners: {
							click: function() {
								this.up('window').close();
							}
						}
					}];
	}

	var portals_view_window_config = Ext.create('Ext.Window', {
		title: 'Portal Definition for Portal - ' + portal_name,
		width: w-20,
		height: h-20, 
		maximizable: true,
		x: 10,
		y: 10,
		id: 'portal_rawxml',
		modal: true,
		renderTo: document.body,
		headerPosition: 'top',
		layout: {
			type: 'vbox',
			align: 'stretch',
			padding: 0
		},
		items: [ {
			xtype: 'textareafield',
			fieldStyle: 'font-family: monospace',
			id: 'dummy_field2_for_rawxml',
			flex: 10,
			grow: true,
			name: 'dummy_field2_for_rawxml'
		} ],
		bbar: bbar_data,
	});
	var myentry = Ext.getCmp('dummy_field2_for_rawxml');
	myentry.setValue(portal_xml);
	if(! is_portal_admin) {
		myentry.disable();
	}
	portals_view_window_config.show();
}

// Retrieve the report or meta-report raw xml and display in a 
// scrolling text window...

function view_available_report_config(portal,record,is_report_admin) {
	var report_name = record.get('rfile');
	var report_type = record.get('entry_type');
	var report_xml = record.get('raw_xml');

	var h =  this.innerHeight;
	var w = this.innerWidth;

	var portals_view_window_config = Ext.create('Ext.Window', {
		title: 'Report Definition for Report - ' + record.get('rname'),
		width: w-20,
		height: h-20, 
		maximizable: true,
		x: 10,
		y: 10,
		id: 'report_rawxml',
		modal: true,
		renderTo: document.body,
		headerPosition: 'top',
		layout: {
			type: 'vbox',
			align: 'stretch',
			padding: 0
		},
		items: [{
			xtype: 'textareafield',
			fieldStyle: 'font-family: monospace',
			id: 'dummy_field_for_rawxml',
			// anchor: '100% 100%',
			grow: true,
			flex: 10,
			name: 'dummy_field_for_rawxml'
		} ],
		bbar: [{
			xtype: 'button', text: 'Cancel',
				listeners: {
					click: function() {
						this.up('window').close();
					}
				}
			}, 
			'->',
			{
			xtype: 'button', text: 'Save',
				listeners: {
					click: function() {
						var my_panel=this.up('panel');
						my_panel.setLoading('Updating ...');
						// dump all values for store...
						var myentry = Ext.getCmp('dummy_field_for_rawxml');
						var xml_info=myentry.getValue();
						Remote_Actions.set_report_xml(report_name,report_type,xml_info,
								function(provider,response) {
									var res=response.result;
									console.log("parse_result:",res);
									if(res.validated != undefined) {
										my_alert(res.validated,'E',"Invalid XML detected.");
										my_panel.setLoading(false);
									} else if(res.error != undefined) {
										my_alert(res.error,'E',"Failed to update report XML");
										my_panel.setLoading(false);
									} else {
										var my_win = Ext.getCmp('report_rawxml');
										append_status_text("XML updated as requested.");
										// Need to update the value in the store as well....
										record.set('raw_xml',xml_info);
										my_win.close();
									}
								}
						);
					}
				}
			}
		]
	});
	var myentry = Ext.getCmp('dummy_field_for_rawxml');
	myentry.setValue(report_xml);
	if(! is_report_admin) {
		myentry.disable();
	}
	portals_view_window_config.show();
}

function portals_admin() {
// We create a new window with a list to show all report types.
// XXX
	var h =  this.innerHeight;
	var w = this.innerWidth;
	var all_portals_grid = Ext.data.StoreManager.lookup('all_portals_grid');
	all_portals_grid.removeAll();
	var portals_admin_window = Ext.create('Ext.Window', {
		title: 'All Available Portals',
		width: w-2,
		height: h-2, 
		maximizable: true,
		x: 1,
		y: 1,
		id: 'AllportalsWindow',
		modal: true,
		renderTo: document.body,
		headerPosition: 'top',
		layout: 'border',
		items: [{
			region: 'center',
			layout: {
				type: 'vbox',
				align: 'stretch'
			},
			items: [{
				flex: 1,
				id: 'all_portals_list',
				xtype: 'grid',
				store: all_portals_grid,
				viewConfig: {
					stripeRows: true,
					trackOver: false
				},
			// tbar: [{
				// height: 32,
				// width: 32,
				// icon: 'resources/images/chart.bmp',
				// text: 'Counts',
				// iconAlign: 'top',
				// id: 'portal_view_chart_btn1',
				// tooltip: 'Report Counts Chart',
				// disabled: true,
				// listeners: {
					// click: function() {
						// show_portal_info_chart1(portal,portals_reports_grid,'count');
					// }
				// }
			// },{
				// height: 32,
				// width: 32,
				// icon: 'resources/images/chart.bmp',
				// text: 'Sizes',
				// iconAlign: 'top',
				// id: 'portal_view_chart_btn2',
				// tooltip: 'Report Storage Chart',
				// disabled: true,
				// listeners: {
					// click: function() {
						// show_portal_info_chart1(portal,portals_reports_grid,'size');
					// }
				// }
			// },{
				// height: 32,
				// width: 32,
				// icon: 'resources/images/refresh.gif',
				// iconAlign: 'top',
				// id: 'portal_view_chart_btn3',
				// text: 'Refresh',
				// tooltip: 'Refresh Window Contents',
				// cls: 'x-btn-text-icon',
				// disabled: true,
				// listeners: {
					// click: function() {
						// populate_portal_reports_list(portal);
					// }
				// }
			// },{
				// icon: 'resources/images/deeplink.gif',
				// iconAlign: 'top',
				// id: 'portal_generate_deeplink',
				// text: 'Deeplink',
				// tooltip: 'Generate Deeplink to Portal',
				// cls: 'x-btn-text-icon',
				// disabled: true,
				// listeners: {
					// click: function() {
						// show_deeplink_dialog(portal);
					// }
				// }
			// }],
				columns: [
					{header: 'Description', flex:7, dataIndex: 'name'},
					{header: 'Report Count', flex:1, dataIndex: 'rcount'},
					{header: 'Meta Report Count', flex:1, dataIndex: 'mrcount'},
					{header: 'User Count', flex:1, dataIndex: 'ucount'},
					{xtype: 'actioncolumn', flex:1, sortable: false,
						text: 'Actions',
						items: [{
							icon: 'resources/images/del_16.gif',
							tooltip: 'Delete Portal',
							disabled: false,
							handler: function(grid, rowIndex, colIndex) {
								var rec = all_portals_grid.getAt(rowIndex);
								portal_delete(rec,all_portals_grid);
							}
						},{
							icon: 'resources/images/add_16.gif',
							tooltip: 'Duplicate Portal',
							disabled: false,
							handler: function(grid, rowIndex, colIndex) {
								var rec = all_portals_grid.getAt(rowIndex);
								portal_duplicate(rec,all_portals_grid);
							}
						},{
							icon: 'resources/images/xml.gif',
							tooltip: 'Edit Portal XML',
							disabled: false,
							handler: function(grid, rowIndex, colIndex) {
								var rec = all_portals_grid.getAt(rowIndex);
								view_available_portal_config(rec,1,all_portals_grid);
							}
						} ]
					}
				]
			}]
		}]
	});
	portals_admin_window.show();
	portals_admin_window.setLoading("Retrieving...");
	var proxy_obj = new Ext.data.proxy.Ajax({
		url: 'cgi_bin/get_portal_instances.pl',
		reader: {
			root: 'portals',
			totalProperty: 'total',
			successProperty: 'success'
		}
	});
	// Set up the proxy for the GUI grid after loading in portal info...
	all_portals_grid.setProxy(proxy_obj);
	all_portals_grid.load({
		scope: this,
		callback: function(records,operation,success) {
			portals_admin_window.setLoading(false);
			}
		});
}

function reports_admin() {
	var h =  this.innerHeight;
	var w = this.innerWidth;
	var all_reports_grid = Ext.data.StoreManager.lookup('all_reports_grid');
	all_reports_grid.removeAll();
	var reports_admin_window = Ext.create('Ext.Window', {
		title: 'All Available Reports',
		width: w-2,
		height: h-2, 
		maximizable: true,
		x: 1,
		y: 1,
		id: 'AllreportsWindow',
		modal: true,
		renderTo: document.body,
		headerPosition: 'top',
		layout: 'border',
		items: [{
			region: 'center',
			layout: {
				type: 'vbox',
				align: 'stretch'
			},
			items: [{
				flex: 1,
				id: 'all_reports_list',
				xtype: 'grid',
				store: all_reports_grid,
				viewConfig: {
					stripeRows: true,
					trackOver: false
				},
			tbar: [{
				height: 32,
				width: 32,
				icon: 'resources/images/chart.bmp',
				text: 'Add',
				iconAlign: 'top',
				id: 'report_add_new_btn1',
				tooltip: 'Define new report',
				disabled: true,
				listeners: {
					click: function() {
						add_new_report();
					}
				}
			} ],
			columns: [
				{header: 'Description', flex:4, dataIndex: 'rname', renderer: _reports_list_grid_desc},
				{header: 'Content Type', flex:1, dataIndex: 'rtype'},
				{header: 'Report Type', flex:1, hidden: true, dataIndex: 'reptype', renderer: function(s) {
					if(s==undefined || s=="") { return "Regular"; }
					if(s=="M") { return "Meta"; }
					return "Regular";
				} },
				{header: 'Host', flex:1, dataIndex: 'rhost'},
				// {header: 'Latest Report', flex:1, dataIndex: 'rdate', renderer: _reports_list_grid_render_date},
				// {header: 'Report Count', flex:1, dataIndex: 'rcount'},
				// {header: 'Storage', flex:1, dataIndex: 'rsize', hidden: true, renderer: _reports_list_grid_render_size},
				{header: 'XML File', flex:1, hidden: true, dataIndex: 'filename'},
				{header: 'Directory', flex:1, hidden: true, dataIndex: 'rdir'},
				{header: 'Pattern', flex:1, hidden: true, dataIndex: 'rfile'},
				{header: 'Date/Naming', flex:1, hidden: true, dataIndex: 'display_name'},
				{xtype: 'actioncolumn', flex:1, sortable: false,
					text: 'Actions',
					items: [{
						icon: 'resources/images/admin.gif',
						tooltip: 'Duplicate Report',
						disabled: false,
						handler: function(grid, rowIndex, colIndex) {
							var rec = all_reports_grid.getAt(rowIndex);
							report_duplicate(rec,all_reports_grid);
						}
					},{
						icon: 'resources/images/deeplink.gif',
						tooltip: 'Delete Report',
						disabled: false,
						handler: function(grid, rowIndex, colIndex) {
							var rec = all_reports_grid.getAt(rowIndex);
							report_delete(rec,all_reports_grid);
						}
					},{
						icon: 'resources/images/xml.gif',
						tooltip: 'Edit Raw XML',
						disabled: false,
						handler: function(grid, rowIndex, colIndex) {
							var rec = all_reports_grid.getAt(rowIndex);
							console.log("rec:",rec);
							var rep_name=rec.get('rname');
							view_available_report_config(null,rec,1);
						}
					},{
						icon: 'resources/images/deeplink_meta.gif',
						tooltip: 'Edit Report',
						disabled: false,
						handler: function(grid, rowIndex, colIndex) {
							var rec = all_reports_grid.getAt(rowIndex);
							var reptype=rec.get('reptype');
							if(reptype == 'M') {
								my_alert("GUI edit of Meta Reports not yet available.",'E',"Not Implemented");
							} else {
								var rep_name=rec.get('rname');
								edit_add_report_window(rec,1,function() {all_reports_grid.load(); console.log("Here3"); });
							}
						}
					} ]
				} ]
			}]
		}]
	});
	reports_admin_window.show();
	reports_admin_window.setLoading("Retrieving...");
	// var proxy_obj = new Ext.data.proxy.Ajax({
		// url: 'cgi_bin/get_portal_instances.pl',
		// reader: {
			// root: 'portals',
			// totalProperty: 'total',
			// successProperty: 'success'
		// }
	// });
	// Set up the proxy for the GUI grid after loading in portal info...
	// all_reports_grid.setProxy(proxy_obj);
	all_reports_grid.load({
		scope: this,
		callback: function(records,operation,success) {
			reports_admin_window.setLoading(false);
			}
		});
}

// Maybe the user wishes to delete the portal - so pop a 
// confirmation request...

function portal_delete(rec,data_store) {
var pname=rec.get('name');

	Ext.MessageBox.confirm('Delete Portal?',"Delete Portal '" + pname + "'?",
		function(btn) {
			if(btn == "no") {
				return;
			}
			// Delete the portal and then refresh...
			Remote_Actions.delete_portal_by_name(pname,
				function(provider,response) {
					var res=response.result;
					if(res.error!=undefined) {
							my_alert(res.error,'E',"Unexpected Error");
							return;
					}
					if(data_store !== undefined) {
						data_store.load();
					}
				}
			);
		}
	);
}

// Ask whether to delete report, and allow delete
// and update data store if necessary.

function report_delete(rec,data_store) {
var rname=rec.get('filename');
var rdesc=rec.get('rname');

	Ext.MessageBox.confirm('Delete Report?',"Delete Report '" + rdesc + "'?",
		function(btn) {
			if(btn == "no") {
				return;
			}
			// Delete the portal and then refresh...
			var xx=Ext.getCmp('AllreportsWindow');
			if(xx != undefined) {
				xx.setLoading('Updating...');
			}
			Remote_Actions.delete_report(rname,
				function(provider,response) {
					var res=response.result;
					if(res.error!=undefined) {
							if(xx != undefined) {
								xx.setLoading(false);
							}
							my_alert(res.error,'E',"Unexpected Error");
							return;
					}
					if(data_store !== undefined) {
						var xx=Ext.getCmp('AllreportsWindow');
						console.log(xx);
						data_store.load();
						if(xx != undefined) {
							xx.setLoading(false);
						}
					}
				}
			);
		}
	);
}

function report_duplicate(rec,data_store) {
var rname=rec.get('filename');
var rdesc=rec.get('rname');

	Ext.MessageBox.confirm('Duplicate Report?',"Duplicate Report '" + rdesc + "'?",
		function(btn) {
			if(btn == "no") {
				return;
			}
			var panel=Ext.getCmp('AllreportsWindow');
			panel.setLoading("Updating...");
			// Delete the portal and then refresh...
			Remote_Actions.duplicate_report(rname,
				function(provider,response) {
					var res=response.result;
					if(res.error!=undefined) {
							panel.setLoading(false);
							my_alert(res.error,'E',"Unexpected Error");
							return;
					}
					if(data_store !== undefined) {
						var panel=Ext.getCmp('AllreportsWindow');
						data_store.load();
						panel.setLoading(false);
					}
				}
			);
		}
	);
}

function portal_duplicate(rec,data_store) {
var pname=rec.get('name');

	Ext.MessageBox.confirm('Duplicate Portal?',"Duplicate Portal '" + pname + "'?",
		function(btn) {
			if(btn == "no") {
				return;
			}
			// Delete the portal and then refresh...
			Remote_Actions.duplicate_portal_by_name(pname,
				function(provider,response) {
					var res=response.result;
					if(res.error!=undefined) {
							my_alert(res.error,'E',"Unexpected Error");
							return;
					}
					if(data_store !== undefined) {
						data_store.load();
					}
				}
			);
		}
	);
}

function view_available_reports(portal,record,rep_mtime) {

	var myGrid = Ext.getCmp('portalsWindow');
    myGrid.setTitle('Available Reports - ' + portal + " - Showing Reports for '" + record.get('rname') +"'.");
	var report = record.get('rfile');
	var panel = Ext.getCmp('portal_reports_list_reps');
	panel.setLoading("Retrieving...");
	if(record.get('entry_type') == "M") {
		// Here we can use a memory proxy, since the
		// report information is available via : 
		console.log(GRI_glob_portal_meta_reports_info[report]);
		var records = [];
		var ds=Ext.data.StoreManager.lookup('portal_reports_list_grid');
		for(var i=0; i < GRI_glob_portal_meta_reports_info[report].count; i++) {
			var m = GRI_glob_portal_meta_reports_info[report].records[i];
			// console.log("m fname=:" + m.fname);
			// console.log("m fdate_str=:" + m.fdate_str);
			// console.log("m fsize:=" + m.fsize);
			records.push(
				{
					rfile: m.fname,
					rdate: m.fdate_str,
					rsize: m.fsize,
					rmtime: m.fmtime,
					portal: portal,
					report: report
				});
		}
		var proxy_obj = new Ext.data.proxy.Memory({ data: records, model: 'report_instance_list' });
		ds.setProxy(proxy_obj);
		ds.load();
		panel.setLoading(false);
		if(rep_mtime !== undefined) {
			// We have been given a report instance (of a meta-report?)
			// and so should view this instance...
		}
		return;
	}
	// The store should be changed using setProxy to proxy for
	// the reports required...
	var report_enc = base64_encode(report);
	var portal_enc = base64_encode(portal);
	var proxy_obj = new Ext.data.proxy.Ajax({
		url: 'cgi_bin/get_report_instances.pl?report=' + report_enc + '&portal=' + portal_enc,
		reader: {
			root: 'reports',
			totalProperty: 'total',
			successProperty: 'success'
		}
	});
	var ds=Ext.data.StoreManager.lookup('portal_reports_list_grid');
	ds.setProxy(proxy_obj);
	var fn=function(r,o,s) { ; };
	if(rep_mtime !== undefined) {
		if(rep_mtime==-1) {
			ds.sort('rmtime','DESC');
			fn=function(r,o,s) {
				if(r.length < 1) {
					my_alert('No Reports','E','No repost instances for report exist.');
					return;
				}
				var rec=ds.getAt(0);
				view_report_content(rec,0);
			};
		} else {
			console.log("Setting up call back for report insance load...");
			fn=function(r,o,s) {
				if(r.length < 1) {
					my_alert('No Reports','E','No repost instances for report exist.');
					return;
				}
				var rec_no = ds.findExact('rmtime',rep_mtime);
				console.log("Store record count:" + ds.count());
				if(rec_no==-1) {
					my_alert('Invalid Report','E','Unable to locate the specified report .');
				} else {
					var rec=ds.getAt(rec_no);
					view_report_content(rec,0);
				}
			}
		}
	}
	ds.load(fn);
	panel.setLoading(false);
	// Remote_Actions.get_portal_report_instances(portal,report,
		// function(provider,response) {
			// var ds=Ext.data.StoreManager.lookup('portal_reports_list_grid');
			// var res=response.result;
			// if(res.error!=undefined) {
				// alert(res.error);
			// } else {
				// ds.removeAll();
				// var trec=res.count;
				// for( var i=0; i<trec; ++i) {
					// ds.add({
						// rfile: res.records[i].fname,
						// rsize: res.records[i].fsize,
						// rmtime: res.records[i].fmtime,
						// rdate: res.records[i].fdate_str,
						// portal: portal,
						// report: report
					// });
				// }
				// panel.setLoading(false);
			// }
		// }
	// );
}

function view_report_content(r,send_as_email) {
	// We have access to the following...
	// {name: 'rfile', type: 'string'},
	// {name: 'rdate', type: 'string'},
	// {name: 'rsize', type: 'int'},
	// {name: 'portal', type: 'string'},
	// {name: 'report', type: 'string'}
	//
	// However we need details of the report details, such as type, formating, etc...
	var ds=Ext.data.StoreManager.lookup('portals_reports_grid');
	var rep_name=r.get('report');
	var report_date=r.get('rdate');
	var report_mtime=r.get('rmtime');
	var my_index = ds.findExact("rfile",rep_name);
	var portal_rec = ds.getAt(my_index);
	var content_type = portal_rec.get('rtype');
	var report_desc = portal_rec.get('rname');
	var report_attrs = portal_rec.get('attrs');
	var report_display_name = portal_rec.get('display_name');
	var report_dynamic_type = portal_rec.get('dynamic_convert_type');
	var entry_type = portal_rec.get('entry_type');
	var raw_xml = portal_rec.get('raw_xml');
	// Get the particular instance report content and
	// render to a new window window.open() - or embed if text/html?
	console.log("portal      : " + r.get('portal'))
	console.log("report      : " + r.get('report'))
	console.log("file        : " + r.get('rfile'))
	console.log("mtime       : " + r.get('rmtime'))
	console.log("rdate       : " + r.get('rdate'))
	console.log("type        : " + content_type);
	console.log("entry_type  : " + entry_type);
	console.log("raw_xml     : " + raw_xml);

	// For certain types (chart) we actually parse the xml, get the raw data 
    // and handle directly from javascript ... else call populate window to do the work...
    if(entry_type == "M" && content_type == "chart") {
		var portal=r.get('portal');
		var report=r.get('report');
		var rmtime=r.get('rmtime');
		var rdate=r.get('rdate');

		// Chart type meta-reports only define a single report, hence
		// report instance parameter is always 0 for first report definition.
		Remote_Actions.get_meta_report_contents_by_mtime(portal,report,0,rmtime,rdate,
			function(provider,response) {
				var res=response.result;
				if(res.error!=undefined) {
						my_alert(res.error,'E',"Unexpected Error");
						return;
				}
				console.log(res);
				xx_internal_chart_from_xml(portal,report,rmtime,entry_type,content_type,rdate,raw_xml,res.content);
			}
		);
		return;
	}
	populate_window(r.get('portal'),r.get('report'),r.get('rmtime'),entry_type,r.get('rdate'),raw_xml);
}

function gen_line_or_area_chart(o) {
	// o is object with at least the following properties...
	// title, width, height
	// Optional in the future
	// x_axis_title, x_axis_values,
	// y_axis_title, chart_type
	//
	// Actual data series are also passed as part of the object using the 
	// following attributes:
	//
	// series_N - array of valuse... N==1 to start...
	// series_N_title - title for that series of values...
	var chart_type = o.chart_type;
	var y_axis_title = "Default Y axis title";
	var x_axis_title = "Default X axis title";
	var store = undefined;
	if(o.hasOwnProperty("chart_type")) {
		chart_type = o.chart_type;
	}
	if(o.hasOwnProperty("y_axis_title")) {
		y_axis_title=o.y_axis_title;
	}

	console.log(o);
	if(o.chart_type == "pie") {
		// Firslty lets create a store for the fields, with fields name and value1
		var s1 = new Ext.data.ArrayStore({
			autoDestroy: true,
			storeId: 'chart_store_' + c,
			fields: ['field1','name']
		});
		var c=1;
		while(true) {
			var f="series_" + c;
			var f2="series_" + c + "_title";
			if(! o.hasOwnProperty(f)) {
				break;
			}
			var el={};
			el.field1=o[f][0];
			el.name=o[f2];
			s1.add(el);
			c++;
		}

		console.log(s1);
		var meta_report_chart = Ext.create('Ext.Window', {
			title: o.title,
			width: o.width-2,
			height: o.height-2, 
			maximizable: true,
			modal: true,
			renderTo: document.body,
			layout: 'fit',
			items: {
				id: 'meta_chart',
				xtype: 'chart',
				shadow: true,
				animate: false,
				store: s1,
				theme: 'Base:gradients',
				series: [{
					type: 'pie',
					field: 'field1',
					showInLegend: true,
					label: {
						field: 'name',
						display: 'rotate',
						contrast: true
					}
				}]
			}
		});
		return({chart: meta_report_chart, chartid: 'meta_chart'});
	}

	// For guages we do not actually need stores since only
	// showing a single value. The alernative is 3 desc,min,max,actual lines, so if 
	// series.length==3 we do the above, otherwise use first value and min/max
	// settings from gauge_min and gauge_max.

	if(o.chart_type == "gauges") {
		var report_chart_items=[];
		// Append gauge items in the above array now...
		var c=1;
		var c2=1;
		var ids_list=[];
		var max_col=o.gauge_cols;
		var cur_col=1;
		while(true) {
			var f="series_" + c;
			var f2="series_" + c + "_title";
			if(! o.hasOwnProperty(f)) {
				break;
			}
			console.log(ids_list);
			ids_list.push(f);
			var s1 = new Ext.data.ArrayStore({
				autoDestroy: true,
				storeId: 'chart_store_' + c,
				fields: ['field1']
			});
			var el={};
			el.field1=o[f][0];
			s1.add(el);
			var _min=o.gauge_min;
			var _max=o.gauge_max;
			// If the lines contina value,min,max then set it now.
			if(o[f].length>2) {
				_min=o[f][1];
				_max=o[f][2];
			}
			report_chart_items.push({
				id: 'meta_chart_' + c,
				frame: true,
				xtype: 'chart',
				title: o[f2],
				width: 200,
				height: 200,
				shadow: true,
				animate: false,
				store: s1,
				insetPadding: 10,
				showInLegend: true,
				flex: 1,
				legend: {
					position: 'right'
				},
				axes: [{
					type: 'gauge',
					position: 'gauge',
					minimum: _min,
					maximum: _max,
					steps: (_max - _min)/10,
					margin: -10
				}],
				series: [{
					type: 'gauge',
					field: 'field1',
					donut: false
				}]
			});
			c++;
			cur_col++;
			if(cur_col>max_col) {
				// We push text itmes to appear under guages
				while(c2<c) {
					f2="series_" + c2 + "_title";
					report_chart_items.push({
						id: 'meta_chart_' + c2 + "_title",
						xtype: 'label',
						html: '<center>' + o[f2] + '</center>'
					});
					c2++;
				}
				cur_col=1;
			}
		}
		// If the current column is not at the end of the
		// row pad out if necessary...
		while(cur_col<=max_col) {
			report_chart_items.push({
				id: 'meta_chart_' + cur_col + "_pad1",
				xtype: 'label',
				html: ''
			});
			cur_col++;
		}
		cur_col=1;
		while(c2<c) {
			f2="series_" + c2 + "_title";
			report_chart_items.push({
				id: 'meta_chart_' + c2 + "_title",
				xtype: 'label',
				html: '<center>' + o[f2] + '</center>'
			});
			c2++;
			cur_col++;
		}
		while(cur_col<=max_col) {
			report_chart_items.push({
				id: 'meta_chart_' + cur_col + "_pad2",
				xtype: 'label',
				html: ''
			});
			cur_col++;
		}
		// Create a grid based on the number of columns specified...
		var meta_report_chart = Ext.create('Ext.Window', {
			title: o.title,
			width: o.width-2,
			height: o.height-2, 
			maximizable: true,
			modal: true,
			// renderTo: document.body,
			layout: {
				type: 'table',
				columns: o.gauge_cols
			},
			items: report_chart_items
		});
		return({chart: meta_report_chart, chartid: ids_list});
	}

	var flist = [];
	var flist2 = [];
	// dynamically build up list of fields before creating store...
	if(o.hasOwnProperty("x_axis_title")) {
		x_axis_title=o.x_axis_title;
		flist.push({name: 'x_axis', type: 'string'});
	} else {
		my_alert("Missing label axis information.",'E','Internal error');
		return;
	}

	var c=1;
	var max_elements=-1;
	var my_series=[];
	if(chart_type == "line") {
		while(true) {
			var f="series_" + c;
			if(o.hasOwnProperty(f)) {
				flist.push({name: f, type: 'float'});
				flist2.push(f);
				if(o[f].length > max_elements) {
					max_elements=o[f].length-1;
				}
				// Add the series of the values to display
				my_series.push({
					title: o[f + "_title"],
					type: chart_type,
					// axis: 'bottom',
					// highlight: true,
					// label: {
						// display: 'insideEnd',
						// field: whatname,
						// renderer: Ext.util.Format.numberRenderer(whatformat),
						// orientation: 'horizontal',
						// 'text-anchor': 'middle'
					// },
					axis: 'left',
					xField: 'x_axis',
					yField: f,
					markerConfig: {
						type: 'circle',
						size: 3,
						radius: 3,
						'stroke-width': 0
					}
				});
			} else {
				break;
			}
			c=c+1;
		}
	} else {
		// for area the yField is all the Y fields at once
		var f="???";
		var _f="???";
		var flist3=[];
		while(true) {
			f="series_" + c;
			if(o.hasOwnProperty(f)) {
				_f=f
				flist.push({name: f, type: 'float'});
				flist2.push(f);
				flist3.push(o[f + "_title"]);
				if(o[f].length > max_elements) {
					max_elements=o[f].length-1;
				}
			} else {
				break;
			}
			c=c+1;
		}
		my_series.push({
			// title: o[_f + "_title"],
			title: flist3,
			type: chart_type,
			// axis: 'bottom',
			// highlight: true,
			// label: {
				// display: 'insideEnd',
				// field: whatname,
				// renderer: Ext.util.Format.numberRenderer(whatformat),
				// orientation: 'horizontal',
				// 'text-anchor': 'middle'
			// },
			xField: 'x_axis',
			yField: flist2
		});
	}
	// Now ready to define the store itself
	my_store = new Ext.data.ArrayStore({
		autoDestroy: true,
		storeId: 'chart_store',
		fields: [flist]
	});

	// Now need to split all series and split them
	// into records to add to the store...
	var l=0;
	while(l<=max_elements) {
		el={};
		if(l<=o.x_axis_values.length) {
			el.x_axis=o.x_axis_values[l];
		}
		for(var ii=0; ii < flist2.length; ii++) {
			cs=flist2[ii];
			if(l<=o[cs].length) {
				el[cs]=o[cs][l];
			}
		}
		my_store.add(el);
		l=l+1;
	}
	var use_grid=false;
	if(max_elements<50) {
		use_grid=true;
	}
	var y_whatformat="0,0"; // could be a parameter via y_axis_format

	var meta_report_chart = Ext.create('Ext.Window', {
		title: o.title,
		width: o.width-2,
		height: o.height-2, 
		maximizable: true,
		modal: true,
		renderTo: document.body,
		layout: 'fit',
		items: {
			id: 'meta_chart',
			xtype: 'chart',
			shadow: true,
			animate: false,
			store: my_store,
			legend: {
				position: 'right'
			},
			axes: [{
				type: 'Category',
				position: 'bottom',
				fields: ['x_axis'],
				title: x_axis_title,
				grid: use_grid,
				label: {
					rotate: {degrees: 270 }
				}
			},{
				type: 'Numeric',
				position: 'left',
				fields: flist2,
				// label: {
					// renderer: chart_numeric_renderer
				// },
				label: Ext.util.Format.numberRenderer("0,0"),
				grid: use_grid,
				title: y_axis_title,
				maximum: o.y_axis_max,
				minimum: o.y_axis_min
			}],
			series: my_series
		}
	});
	return({chart: meta_report_chart, chartid: 'meta_chart'});
}

// Number rendering in charts has problems if axis labels is too large - this
// gets round the problem for 4.0.2.

function chart_numeric_renderer(item) {
	var y2=Ext.util.Format.numberRenderer('0.0',item);
	var y=Ext.util.Format.number(item, '0.0') + ' L';
	y=y+1;
	console.log("y=" + y);
	return y;
	if (item >= 100000) {
		// var v = (item*1 >= 100000) ? item*1/100000 : 0;
		return Ext.util.Format.number(item, '0.0') + ' L';
	}
	else if (item < 10) {
		return Ext.util.Format.number(item, '0.00');       
	}
	else {
		return item;
	}
}

function xx_internal_chart_from_xml(portal,report,mtime,entry_type,content_type,rdate,raw_xml,content) {
	// Read in the xml ...
	var xmlDoc;
	if(window.DOMParser) {
		var parser=new DOMParser();
		xmlDoc=parser.parseFromString(raw_xml,"text/xml");
	} else { // IE older versions...
		xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async="false";
		xmlDoc.loadXML(raw_xml);
	}
	// Get the meta-info elements as a custom object using elements as 
	// attributes where "t" and "a_" indicies for data.

	var meta_info=xmlDoc.getElementsByTagName("meta-info")[0];
	var a_mi={};
	for(c in meta_info.childNodes) {
		var x=meta_info.childNodes[c];
		if(x.localName != undefined) {
			a_mi[x.localName]={}
			a_mi[x.localName]["t"]=x.textContent;
			for(c2 in x.attributes) {
				var k="a_"+x.attributes[c2].nodeName;
				a_mi[x.localName][k]=x.attributes[c2].nodeValue;
			}
		}
	}
	var width=600;
	var height=400;
	var title="My Chart";
	var chart_content_type="line";
	var x_axis_line=1;
	var x_axis_col=1;
	var y_axis_title="";
	var title_col="";
	var y_axis_max=undefined;
	var y_axis_min=undefined;
	var my_gauge_cols=2;
	// If the chart_hints element is available and height, width and title
	// attributes are available then use them.
	if(a_mi.hasOwnProperty("chart_hints")) {
		if(a_mi["chart_hints"].hasOwnProperty("a_width")) {
			width=parseInt(a_mi["chart_hints"]["a_width"]);
		}
		if(a_mi["chart_hints"].hasOwnProperty("a_height")) {
			height=parseInt(a_mi["chart_hints"]["a_height"]);
		}
		if(a_mi["chart_hints"].hasOwnProperty("a_title")) {
			title=a_mi["chart_hints"]["a_title"];
		}
		// Gauge charts can have lots of charts in same window
		// shown in grid format.
		if(a_mi["chart_hints"].hasOwnProperty("a_cols")) {
			my_gauge_cols=parseInt(a_mi["chart_hints"]["a_cols"]);
		}
	}

	// We have the xml and the content so do somethnig with it ....
	// First when type = stack-line handle now...
	if(a_mi["type"]["t"] == "stack-line" || a_mi["type"]["t"] == "line" ||
		a_mi["type"]["t"] == "gauges" || a_mi["type"]["t"] == "pie") {
		console.log(a_mi);
		if(! a_mi["content_format"].hasOwnProperty("a_type")) {
			my_alert('Missing expected content_format element for chart definition.','E',"Unexpected Error");
			return;
		}
		var type=a_mi["content_format"]["a_type"];
		var start_item=2;
		var start_col=2;
		var gauge_min=0;
		var gauge_max=50;
		if(a_mi["content_format"].hasOwnProperty("a_gauge_min")) {
			gauge_min=parseInt(a_mi["content_format"]["a_gauge_min"]);
		}
		if(a_mi["content_format"].hasOwnProperty("a_gauge_max")) {
			gauge_max=parseInt(a_mi["content_format"]["a_gauge_max"]);
		}
		if(a_mi["content_format"].hasOwnProperty("a_y_axis_max")) {
			y_axis_max=parseInt(a_mi["content_format"]["a_y_axis_max"]);
		}
		if(a_mi["content_format"].hasOwnProperty("a_y_axis_min")) {
			y_axis_min=parseInt(a_mi["content_format"]["a_y_axis_min"]);
		}
		if(a_mi["content_format"].hasOwnProperty("a_x_axis_line")) {
			x_axis_line=parseInt(a_mi["content_format"]["a_x_axis_line"]);
		}
		if(a_mi["content_format"].hasOwnProperty("a_x_axis_col")) {
			x_axis_col=parseInt(a_mi["content_format"]["a_x_axis_col"]);
		}
		if(a_mi["content_format"].hasOwnProperty("a_y_axis_title")) {
			y_axis_title=a_mi["content_format"]["a_y_axis_title"];
		}
		if(a_mi["content_format"].hasOwnProperty("a_start_col")) {
			start_col=parseInt(a_mi["content_format"]["a_start_col"]);
		}
		if(a_mi["content_format"].hasOwnProperty("a_start_item")) {
			start_item=parseInt(a_mi["content_format"]["a_start_item"]);
		}
		var title_item=1;
		if(a_mi["content_format"].hasOwnProperty("a_title_item")) {
			title_item=parseInt(a_mi["content_format"]["a_title_item"]);
		}
		var start_line=2;
		if(a_mi["content_format"].hasOwnProperty("a_start_line")) {
			start_line=parseInt(a_mi["content_format"]["a_start_line"]);
		}
		var lines=1;
		var cols=1;
		if(a_mi["content_format"].hasOwnProperty("a_cols")) {
			cols=parseInt(a_mi["content_format"]["a_cols"]);
		}
		if(a_mi["content_format"].hasOwnProperty("a_lines")) {
			lines=parseInt(a_mi["content_format"]["a_lines"]);
		}
		var aa=content.split("\n");
		
		// generate a chart now. :)
		var o={};
		var o_setup=0;
		if(type == "lines" && a_mi["type"]["t"] == "gauges") {
			lines=aa.length;
			o.chart_type="gauges";
			o.width=width;
			o.height=height;
			o.gauge_min=gauge_min;
			o.gauge_max=gauge_max;
			o.gauge_cols=my_gauge_cols;
			o.title=title;
			var series_n=1;
			for(var cline=start_line-1; cline<lines-1; cline++) {
				var xx=aa[cline].split(",");
				var xxx=[];
				for(var i=start_item-1; i < xx.length; i++) {
					xxx.push(parseFloat(xx[i]));
				}
				o["series_" + series_n]=xxx;
				o["series_" + series_n + "_title"]=xx[title_item-1];
				series_n++;
			}
			o_setup=1;
		}
		// Handle a lines based pie chart. Each line of data
		// contributes a label and a single value to the total
		// of a single pie. Support multiple pies in the future
		// like we do for table-based gauge output.
		if(type == "lines" && a_mi["type"]["t"] == "pie") {
			lines=aa.length;
			o.chart_type="pie";
			o.width=width;
			o.height=height;
			o.title=title;
			var series_n=1;
			for(var cline=start_line-1; cline<lines-1; cline++) {
				var xx=aa[cline].split(",");
				var xxx=[];
				for(var i=start_item-1; i < xx.length; i++) {
					xxx.push(parseFloat(xx[i]));
				}
				o["series_" + series_n]=xxx;
				o["series_" + series_n + "_title"]=xx[title_item-1];
				series_n++;
			}
			o_setup=1;
		}
		if(o_setup==0 && type == "lines") {
			o.title=title;
			o.y_axis_title=y_axis_title;
			o.width=width;
			o.height=height;
			// o.chart_type="line";
			if(a_mi["type"]["t"] == "stack-line") {
				o.chart_type="area";
			} else {
				o.chart_type="line";
			}
			o.x_axis_title="Unknown";
			o.y_axis_max=y_axis_max;
			var x_axis_values=[];
			// Handle lines format data first...
			
			if(aa.length>x_axis_line) {
				var xx=aa[x_axis_line-1].split(",");
				if(title_item-1<xx.length) {
					o.x_axis_title=xx[title_item-1];
				}
				// plop all the other values after start_item
				for(var i=start_item-1; i < xx.length; i++) {
					x_axis_values.push(xx[i]);
				}
				o.x_axis_values=x_axis_values;
			}
			var series_n=1;
			for(var cline=start_line-1; cline<start_line+lines-1; cline++) {
				var xx=aa[cline].split(",");
				var xxx=[];
				for(var i=start_item-1; i < xx.length; i++) {
					xxx.push(parseFloat(xx[i]));
				}
				o["series_" + series_n]=xxx;
				o["series_" + series_n + "_title"]=xx[title_item-1];
				series_n++;
			}
			o_setup=1;
		}
		if(o_setup==0) {
			// cols items, make use of the following vars... x_axis_col, start_col, cols
			o.title=title;
			o.y_axis_title=y_axis_title;
			o.width=width;
			o.height=height;
			if(a_mi["type"]["t"] == "stack-line") {
				o.chart_type="area";
			} else {
				o.chart_type="line";
			}
			o.x_axis_title="Unknown";
			o.y_axis_max=y_axis_max;
			// o.chart_type="area";
			var x_axis_values=[];


			// Set X axis title from item_item (line) and x_axis_col
			
			if(aa.length>title_item) {
				var ss=aa[title_item-1].split(",")
				if(ss.length >x_axis_col) {
					o.x_axis_title=ss[x_axis_col-1];
				}
			}
				
			// From title_item onwards we gather x_axis_values using x_axis_col-1
			if(aa.length>title_item+1) {
				for(var i=start_item-1; i < aa.length; i++) {
					var ss=aa[i].split(",");
					x_axis_values.push(ss[x_axis_col-1]);
				}
				o.x_axis_values=x_axis_values;
			}

			// Keep the series data by slicing each line and extracting columns...
			var series_n=1;
			for(var c_col=start_col-1; c_col<start_col+cols-1; c_col++) {
				var ss=aa[title_item-1].split(",")
				o["series_" + series_n + "_title"]=ss[c_col]; // Set the series title

				var xxx=[];
				for(var i=start_item-1; i < aa.length; i++) {
					var ss=aa[i].split(",");
					if(ss.length > c_col) {
						xxx.push(parseFloat(ss[c_col])); 
					}
				}
				o["series_" + series_n]=xxx;
				series_n++;
			}
		}
		console.log(o);

		var chart_info=gen_line_or_area_chart(o);
		// o is object with at least the following properties...
		// title, width, height
		// Optional in the future
		// x_axis_title, x_axis_values,
		// y_axis_title, chart_type
		//
		// Actual data series are also passed as part of the object using the 
		// following attributes:
		//
		// series_N - array of valuse... N==1 to start...
		chart_info.chart.show();
		return;
	}
	console.log("Data type not recognised.");
}

function populate_window(portal,report,mtime,entry_type,rdate,xml) {
	// This should be a request since 
	var portal_enc=base64_encode(portal);
	var report_enc=base64_encode(report);
	var mtime_enc=base64_encode(mtime);
	var rdate_enc=base64_encode(rdate);
	var myWindow=window.open("cgi_bin/push_file.pl?portal=" + portal_enc + "&entry_type=" + entry_type + "&report=" + report_enc + "&mtime=" + mtime_enc + "&rdate=" + rdate_enc, "newwin", "height=700, width=800,toolbar=yes,scrollbars=yes,menubar=yes");
	// If ATTACH then the window should now be closed!
}

// Add tooltop to the report description...
function _reports_list_grid_desc(value, metaData, record, rowIndex, colIndex, store) {

	var txt="";
	// console.log(record.data);
	if(record.data.attrs.length > 0) {
		txt="Attributes: " + record.data.attrs;
	}
	if(txt.length>0) {
		txt=txt + "\n" + record.data.dynamic_convert_type;
	} else {
		txt=record.data.dynamic_convert_type;
	}
	metaData.attr = 'ext:tooltip="' + txt + '"';
	return value;
}

function _reports_list_grid_render_date(s) {
	if(s==undefined || s=="") {
		return "";
	}
	var cval=getCookieElement("GRI2_prefs","datefmt");
	if(cval==undefined) {
		cval="DD/MM/YYYY";
	}
	// Take the value and split it into yyyy[0].mm[1].dd[2].hh[3].mm[4].ss[5]
	var bits=s.split('.');
	
	cval = cval.replace(/YYYY/,bits[0]);
	cval = cval.replace(/YY/,bits[0].substr(2,2));
	cval = cval.replace(/MM/,bits[1]);
	cval = cval.replace(/DD/,bits[2]);
	return cval;
}

function _reports_list_grid_render_size(s) {
	if(s==0) {
		return "Empty";
	}
	if(s<1024) {
		return s+" Bytes";
	}
	if(s>=1024 && s<=1024*1024) {
		fl=sprintf("%.1f",s/1024.0);
		return fl+" KiB";
	}
	fl=sprintf("%.1f",s/(1024.0*1024.0));
	return fl+" MiB";
}
// Edit or add a report definition window. Considered to be 'add' if report
// has the value undefined - otherwise is the name of the report to load/edit.
//
// The admin==1 allows the report to be edited otherwise usde to show
// details of an existing report - but read-only.

function edit_add_report_window(report,admin,reload_func) {
	var is_reports_list_Model=0;
	if(report.$className == "reports_list_Model") {
		is_reports_list_Model=1;
	}
	var new_report=0;
	var my_title = 'Add new Report';
	var rname='';
	var filename='';
	var rdir='';
	var rpattern='';
	var rhost='';
	var rtype='';
	var attrs='';
	var display_text='';
	var disabled_entry=true;
	if(admin) {
		disabled_entry=false;
	}
	console.log(report);
	if(report != undefined) {
		// If a meta-report than alert that this is not supported as yet
		if(report.get('entry_type') == "M") {
			my_alert('Editing of Meta-reports is not yet implemented.','I','Functionality not Implemented');
			return;
		}
		if(is_reports_list_Model) {
			console.log("H1");
			rname=report.get('rname');
			rpattern=report.get('rfile');
			rfile=report.get('filename');
		} else {
			console.log("H2");
			rname=report.get('rname');
			rpattern=report.get('rpattern');
			rfile=report.get('rfile');
		}
		if(admin==0) {
			my_title='View configuration of report ' + rname;
		} else {
			my_title='Edit configuration of report ' + rname;
		}
		rdir=report.get('rdir');
		rhost=report.get('rhost');
		rtype=report.get('rtype');
		attrs=report.get('attrs');
		display_text=report.get('display_name');
	} else {
		var new_report=1;
		// Adding new reports to be implemented at the moment...
		my_alert('Adding new reports is not yet implemented.','I','Functionality not Implemented');
		return;
	}
	var h =  this.innerHeight;
	var w = this.innerWidth;
	var report_name;
	var report_type;

	var butts = [
		{ xtype: 'button', text: 'Cancel',
			listeners: {
				click: function() {
					this.up('window').close();
				}
			}
		}];

	if(admin) {
		butts.push('->');
		butts.push(
			{ xtype: 'button', text: 'Save',
				handler: function() {
					var w=this.up('window');
					w.setLoading('Validating Settings...');
					var dir=Ext.getCmp('reportCheckrdir').getValue();
					var hn=Ext.getCmp('reportCheckrhost').getValue();
					var pat=Ext.getCmp('reportCheckrpattern').getValue();
					var msg="";
					if(new_report) {
						msg="add new report";
					} else {
						msg="update existing report";
					}
					Remote_Actions.host_checks(hn,'matches',dir + '/' + pat,
						function(provider,response) {
							var res=response.result;
							var xx=Ext.getCmp('repadd_filecheck_message');
							if(res.error != undefined) {
								// An error has occured, so update message and also
								my_alert(res.error,'E',msg);
								w.setLoading(false);
								return;
							}
							// Get the contents of the other fields
							// So validated the host/dir/pattern setting - though
							// show a warning if the count==0

							var attrs=Ext.getCmp('reportCheckattrs').getValue();
							var desc=Ext.getCmp('reportCheckdesc').getValue();
							var xmlfile=Ext.getCmp('reportCheckfile').getValue();
							var rtype=Ext.getCmp('reportChecktype').getValue();
							var display_text=Ext.getCmp('reportCheckdisplay_text').getValue();
							console.log("attrs: " + attrs);
							console.log("desc: " + desc);
							console.log("xmlfile: " + xmlfile);
							if(new_report==0) {
								Remote_Actions.report_update(xmlfile,desc,attrs,hn,dir,pat,rtype,display_text,
									function(provider,response) {
										var res=response.result;
										var xx=Ext.getCmp('repadd_filecheck_message');
										if(res.error != undefined) {
											my_alert(res.error,'E',msg);
											w.setLoading(false);
											return;
										}
										if(reload_func != undefined) {
											reload_func();
										}
										w.close();
									}
								);
							} else {
								my_alert('Adding new reports is not yet implemented.','I','Functionality not Implemented');
								w.setLoading(false);
							}
						}
					);
					// validate before we attempt to send any changes
					// to the server...
				}
			}
		);
	}

	var ftypes = Ext.create('Ext.data.Store', {
		fields: ['type', 'desc'],
		data : [ ]
	});

	var report_add_edit_view_window = Ext.create('Ext.Window', {
		title: my_title,
		width: 500,
		height: 600, 
		// x: 1,
		// y: 1,
		id: 'reportaddeditview',
		modal: true,
		renderTo: document.body,
		headerPosition: 'top',
		layout: {
			type: 'table',
			columns: 3,
			tableAttrs: {
				style: {
					width: '100%'
				}
			}
		},
		items: [{
			xtype: 'label',
			text: 'Description:',
			width: '20%'
		},{
			xtype: 'textfield',
			disabled: disabled_entry,
			name: 'rname',
			allowBlank: false,
			blankText: 'The one line description of the report cannot be blank',
			value: rname,
			id: 'reportCheckdesc',
			width: 300
		},{
			xtype: 'label',
			text: '',
			width: '10%'
		},{
			xtype: 'label',
			text: 'XML File:'
		},{
			xtype: 'textfield',
			disabled: new_report==1 ? false : true,
			name: 'rfile',
			allowBlank: false,
			blankText: 'The XML file of the report cannot be blank',
			value: rfile,
			id: 'reportCheckfile',
			width: 300
		},{
			xtype: 'button',
			disabled: true, // enable when entry is not blank .. and when not new file
			text: 'Check',
			id: 'reportCheckxmlfile'
		},{
			colspan: 3,
			xtype: 'label',
			html: '<center>Press Check above to validate XML filename</center>',
			margin: 5,
			id: 'xx_01'
		},{
			xtype: 'label',
			text: 'Directory:'
		},{
			xtype: 'textfield',
			disabled: disabled_entry,
			name: 'rdir',
			allowBlank: false,
			value: rdir,
			id: 'reportCheckrdir',
			width: 300
		},{
			xtype: 'button',
			disabled: true, // enable when host is not empty and this is not empty...
			text: 'Check',
			id: 'reportCheckrdir_button',
			handler: function() {
				// This button
				var w=this.up('window');
				w.setLoading('Checking...');
				var dir=Ext.getCmp('reportCheckrdir').getValue();
				var hn=Ext.getCmp('reportCheckrhost').getValue();
				Remote_Actions.host_checks(hn,'dir',dir,
					function(provider,response) {
						var res=response.result;
						var xx=Ext.getCmp('repadd_dircheck_message');
						if(res.error != undefined) {
							// An erro has occured, so update message and also
							xx.setText('<center><font color=red>' + res.error + '</font></center>',false);
						} else {
							xx.setText('<center>Directory ' + dir + ' exists on host ' + hn +  '.</center>',false);
						}
						w.setLoading(false);
					}
				);
			}
		},{
			colspan: 3,
			xtype: 'label',
			html: '<center>Press Check above to validate Directory</center>',
			margin: 5,
			id: 'repadd_dircheck_message'
		},{
			xtype: 'label',
			text: 'File Pattern:'
		},{
			xtype: 'textfield',
			id: 'reportCheckrpattern',
			disabled: disabled_entry,
			name: 'rpattern',
			allowBlank: false,
			value: rpattern,
			width: 300
		},{
			xtype: 'button',
			text: 'Check',
			disabled: true, // enable one host/dir/file are not blank
			id: 'reportCheckrpattern_button',
			handler: function() {
				// This button
				var w=this.up('window');
				w.setLoading('Checking...');
				var dir=Ext.getCmp('reportCheckrdir').getValue();
				var hn=Ext.getCmp('reportCheckrhost').getValue();
				var pat=Ext.getCmp('reportCheckrpattern').getValue();
				Remote_Actions.host_checks(hn,'matches',dir + '/' + pat,
					function(provider,response) {
						var res=response.result;
						var xx=Ext.getCmp('repadd_filecheck_message');
						if(res.error != undefined) {
							// An erro has occured, so update message and also
							xx.setText('<center><font color=red>' + res.error + '</font></center>',false);
						} else {
							xx.setText('<center>Host/Directory/Pattern file match count:' + res.count + '.</center>',false);
						}
						w.setLoading(false);
					}
				);
			}
		},{
			colspan: 3,
			xtype: 'label',
			html: '<center>Press Check above to validate file Pattern</center>',
			margin: 5,
			id: 'repadd_filecheck_message'
		},{
			xtype: 'label',
			text: 'File Host:'
		},{
			xtype: 'textfield',
			disabled: disabled_entry,
			name: 'rhost',
			allowBlank: false,
			value: rhost,
			width: 300,
			id: 'reportCheckrhost'
		},{
			xtype: 'button',
			text: 'Check',
			id: 'reportCheckrhost_button',
			handler: function() {
				var w=this.up('window');
				w.setLoading('Checking...');
				var hn=Ext.getCmp('reportCheckrhost').getValue();
				Remote_Actions.host_checks(hn,'ping','',
					function(provider,response) {
						var res=response.result;
						var xx=Ext.getCmp('repadd_hostcheck_message');
						if(res.error != undefined) {
							// An erro has occured, so update message and also
							xx.setText('<center><font color=red>' + res.error + '</font></center>',false);
						} else {
							xx.setText('<center>Host ' + hn + ' has connectivity.</center>',false);
						}
						w.setLoading(false);
					}
				);
			}
		},{
			colspan: 3,
			xtype: 'label',
			html: '<center>Press Check above to validate Host Connectivity</center>',
			margin: 5,
			id: 'repadd_hostcheck_message'
		},{
			xtype: 'label',
			text: 'Attributes:'
		},{
			xtype: 'textfield',
			disabled: disabled_entry,
			name: 'attrs',
			allowBlank: false,
			value: attrs,
			id: 'reportCheckattrs',
			width: 300
		},{
			xtype: 'label',
			text: ''
		},{
			xtype: 'label',
			text: 'File Type:'
		},{
			// Drop down for a list of types ... empty until we can
			// populate it async!!
			xtype: 'combo',
			disabled: disabled_entry,
			store: ftypes,
			displayField: 'desc',
			valueField: 'type',
			name: 'ftype',
			queryMode: 'local',
			allowBlank: false,
			id: 'reportChecktype',
			width: 300
		},{
			xtype: 'label',
			text: ''
		},{
			colspan: 3,
			xtype: 'label',
			html: '',
			margin: 5
		},{
			xtype: 'label',
			text: 'Display Text:'
		},{
			xtype: 'textfield',
			disabled: disabled_entry,
			name: 'display_text',
			allowBlank: false,
			value: display_text,
			id: 'reportCheckdisplay_text',
			width: 300
		},{
			xtype: 'label',
			text: ''
		} ],
		bbar: butts
	});

	// If disabled_entry == false and content in somf
	// of the entries already then able the relevant buttons
	if(rhost.length>0 && disabled_entry==false) {
		var bb=Ext.getCmp('reportCheckrhost_button');
		bb.enable(true);
	}
	if(rhost.length>0 && rdir.length>0 && disabled_entry==false) {
		var bb=Ext.getCmp('reportCheckrdir_button');
		bb.enable(true);
	}
	if(rhost.length>0 && rdir.length>0 && rpattern.length>0 &&  disabled_entry==false) {
		var bb=Ext.getCmp('reportCheckrpattern_button');
		bb.enable(true);
	}

	// events to enable/disable form 'check' buttons based on the content
	// on the form.

	var xx = Ext.getCmp('reportCheckrpattern');
	xx.addListener('change',function(txt,new_v,old_v,eo) {
		var bb=Ext.getCmp('reportCheckrpattern_button');
		var x2 = Ext.getCmp('reportCheckrhost').getValue();
		var x3 = Ext.getCmp('reportCheckrdir').getValue();
		if(new_v.length!=0 && x2.length!=0 && x3.length!=0) {
			bb.enable(true);
		} else {
			bb.disable(true);
		}
	});
	xx = Ext.getCmp('reportCheckrdir');
	xx.addListener('change',function(txt,new_v,old_v,eo) {
		var bb=Ext.getCmp('reportCheckrdir_button');
		var b2=Ext.getCmp('reportCheckrpattern_button');
		var x2 = Ext.getCmp('reportCheckrhost').getValue();
		if(new_v.length!=0 && x2.length!=0) {
			bb.enable(true);
			var t3=Ext.getCmp('reportCheckrpattern');
			if(t3.getValue().length>0) {
				b2.enable(true);
			}
		} else {
			bb.disable(true);
			b2.disable(true);
		}
	});
	xx = Ext.getCmp('reportCheckrhost');
	xx.addListener('change',function(txt,new_v,old_v,eo) {
		var bb=Ext.getCmp('reportCheckrhost_button');
		var b2=Ext.getCmp('reportCheckrdir_button');
		var b3=Ext.getCmp('reportCheckrpattern_button');
		if(new_v.length==0) {
			bb.disable(true);
			b2.disable(true);
			b3.disable(true);
		} else {
			bb.enable(true);
			var t2=Ext.getCmp('reportCheckrdir');
			var t3=Ext.getCmp('reportCheckrpattern');
			if(t2.getValue().length>0) {
				b2.enable(true);
			}
			if(t2.getValue().length>0 && t3.getValue().length>0) {
				b3.enable(true);
			}
		}
	});

	report_add_edit_view_window.show();
	// Get a list of types and  populate drop-down list...
	Remote_Actions.get_supported_type_desc_list(
		function(provider,response) {
			var res=response.result;
			ftypes.removeAll();
			for(var ct in res) {
				ftypes.add({type: ct, desc: res[ct]});
			}
			// Also set the existing value now we have a list...
			if(rtype in res) {
				var b2=Ext.getCmp('reportChecktype');
				if(b2!=undefined) {
					b2.setValue(res[rtype]);
				}
			}
		}
	);
}

// This should pop a window/form to edit the properties of the specified 
// portal. The information that can be edited will be:
// reports (list of reports part of portal)
// title (text for title of portal)
// users (list of users with access to portal)
// template (non-generic content view for portal)
// owner (owner of portal)
// voters (list of people to vote on portal report/users changes)
// concur_count (number of people that must concur on a change)

function edit_portal_window(portal,title,admin) {

	var my_store = Ext.data.StoreManager.lookup('report_list_selection');
	var my_store2 = Ext.data.StoreManager.lookup('user_list_selection');
	my_store.removeAll();
	my_store2.removeAll();
	// XXX: Sort out
	// if admin == "1" can make changes, otherwise read-only

	// If portal == None then we are creating a
	// new portal, else editing an existing one...
	// So would use portal to get details and populate
	// form - once the form has been created...

	var _included_list={};
	var form_tab1 = Ext.create('Ext.form.Panel', {
                layout: {
                    type: 'vbox',
                    align: 'stretch'
                },
				id: 'portal_edit_tab1',
                border: false,
                bodyPadding: 10,
                fieldDefaults: {
                    labelAlign: 'left',
                    labelWidth: 100,
                    labelStyle: 'font-weight:bold'
                },
                defaults: {
                    margins: '0 0 10 0'
                },
                items: [ {
					xtype: 'tbtext',
					text: "This tab contains the basic portal details.",
				}, {
                    width: 30,
					disabled: true,
					xtype: 'textfield',
                    name: 'portalname',
                    fieldLabel: 'Portal Reference',
                    allowBlank: false
                }, {
                    width: 30,
					xtype: 'textfield',
					name: 'portaltitle',
					fieldLabel: 'Title',
                    allowBlank: false
                }, {
                    width: 30,
					xtype: 'textfield',
					name: 'portaltemplate',
					fieldLabel: 'Template',
                    allowBlank: true
				} ]
	});

	var sm = Ext.create('Ext.selection.RowModel',{
		mode: 'MULTI',
		listeners: {
			deselect: function(sel,rec,idx) {
				return;
				// if(GRI_glob_portal_report_list_updating==1) {
					// return;
				// }
				// var my_store = Ext.data.StoreManager.lookup('report_list_selection');
				// var in_list = my_store.find('rfile',rec.get('rfile'));
				// // console.log("DeSelected: " + rec.get('rfile'));
				// if(in_list==-1) {
					// my_store.add( {
						// rfile: rec.get('rfile'),
						// selected: 0
					// });
				// } else {
					// my_store.getAt(in_list).set('selected',0);
				// }
			},
			select: function(sel,rec,idx) {
				rec.set('included',!rec.get('included'));
				return;
				// var my_store = Ext.data.StoreManager.lookup('report_list_selection');
				// var in_list = my_store.find('rfile',rec.get('rfile'));
				// // console.log("Selected: " + rec.get('rfile'));
				// if(in_list==-1) {
					// my_store.add( {
						// rfile: rec.get('rfile'),
						// selected: 1
					// });
				// } else {
					// my_store.getAt(in_list).set('selected',1);
				// }
			}
		}});
	var portals_reports_grid=Ext.data.StoreManager.lookup('all_reports_grid');
	// portals_reports_grid.removeAll();
	// change the proxy to temporarily add the portal in question to
	// set the included attribute in the results...
	var portal_enc = base64_encode(portal);
	portals_reports_grid.setProxy(
		new Ext.data.proxy.Ajax({
		url: 'cgi_bin/get_reports.pl?portal=' + portal_enc,
		reader: {
			root: 'reports',
			totalProperty: 'total',
			successProperty: 'success',
			reader: 'json'
			}
		})
	);
	portals_reports_grid.load();
	var cellEditing = Ext.create('Ext.grid.plugin.CellEditing', {
		clickstoEdit: 1
	});
	var reports_grid_selector = Ext.create('Ext.grid.Panel', {
		store: portals_reports_grid,
		selModel: sm,
		columns: [
			{text: 'Title', dataIndex: 'rname', flex: 3},
			{text: 'Host', dataIndex: 'rhost', groupable: true, sortable: true},
			{text: 'Type', dataIndex: 'rtype', groupable: true, sortable: true,
				renderer: myRT2},
			{text: 'Reports', dataIndex: 'rcount', hidden: true, sortable: true},
			{text: 'Filename', dataIndex: 'rfile', hidden: true, sortable: true}, // bizzare mash for meta reports!!
			{text: 'Directory', dataIndex: 'rdir', hidden: true, sortable: true},
			{header: 'Included', width:50, dataIndex: 'included',
					xtype: 'checkcolumn', renderer: myCB2}
		],
		bbar: Ext.create('Ext.PagingToolbar', {
			store: portals_reports_grid,
			displayInfo: true,
			listeners: {
				// beforechange is called between subsequent pages, but not
				// before first change...
				beforechange: function(tb,pgnum) {
					// var my_sm = this.up('gridpanel').getSelectionModel();
					// my_sm.setLocked(true);
					// GRI_glob_portal_report_list_updating=1;
					var my_store = Ext.data.StoreManager.lookup('all_reports_grid');
					var my_store2 = Ext.data.StoreManager.lookup('report_list_selection');
					var count=my_store.count();
					for(var i=0; i<count; ++i) {
						var r=my_store.getAt(i);
						var included=r.get('included');
						var filename=r.get('filename');
						var reptype=r.get('reptype');
						var rfile=r.get('rfile');
						var rec_n=my_store2.find('rfile',rfile);
						if(rec_n != -1) {
							var selected_rec=my_store2.getAt(rec_n);
							selected_rec.set('included',included);
						} else {
							my_store2.add({rfile: rfile, reptype: reptype, selected: included, filename: filename});
						}
					}
					// console.log("store_count:" + my_store.count());
				},
				change: function(tb,pgdata) {
					// Probably best just to grab all the included == true
					// and keep them for current grid contents and re-apply
					// the newly put in messages...
					var my_sm = this.up('gridpanel').getSelectionModel();
					var gridp = this.up('gridpanel');
					gridp.show();
					// my_sm.setLocked(false);
					var my_store = Ext.data.StoreManager.lookup('all_reports_grid');
					var my_store2 = Ext.data.StoreManager.lookup('report_list_selection');
					var count=my_store.count();
					console.log("store_count2: " + my_store.count());
					for(var i=0; i<count; ++i) {
						var r=my_store.getAt(i);
						var included=r.get('included');
						var filename=r.get('filename');
						var reptype=r.get('reptype');
						var rfile=r.get('rfile');
						var rec_n=my_store2.find('rfile',rfile);
						if(rec_n == -1) {
							my_store2.add({rfile: rfile, reptype: reptype, selected: included, filename: filename});
						} else {
							var r2=my_store2.getAt(rec_n);
							r.set('included',r2.get('included'));
						}
					}
					GRI_glob_portal_report_list_updating=0;
				},
			},
			displayMsg: 'Displaying reports {0} - {1} of {2}',
			emptyMsg: "No reports defined"}),
		fbar: [
			{
				xtype: 'textfield',
				name: 'report_filter',
				fieldLabel: 'Filter',
				enableKeyEvents: true,
				id: 'portal_edit_tab2_filter'
			},
			{
				xtype: 'button',
				text: 'Filter',
				handler: function() {
					var tf = Ext.getCmp("portal_edit_tab2_filter");
					var filter_text = tf.getValue();
					var report_list=Ext.data.StoreManager.lookup('all_reports_grid');
					// ensure select/deselect don't update our list...
					var my_sm = this.up('gridpanel').getSelectionModel();
					// my_sm.setLocked(true);
					GRI_glob_portal_report_list_updating=1;
					report_list.clearFilter(true);
					report_list.filter('name',filter_text);
					report_list.load();
					GRI_glob_portal_report_list_updating=0;
					// my_sm.setLocked(false);
				}
			}
		]
	});

	// Users list with access to portal...
	var sm2 = Ext.create('Ext.selection.RowModel',{
		mode: 'MULTI',
		listeners: {
			deselect: function(sel,rec,idx) {
				return; 
			},
			select: function(sel,rec,idx) {
				rec.set('included',!rec.get('included'));
				return;
			}
		}});
	var user_list=Ext.data.StoreManager.lookup('user_list');
	user_list.setProxy(
		new Ext.data.proxy.Ajax({
		url: 'cgi_bin/get_users.pl?portal=' + portal_enc,
		reader: {
			root: 'users',
			totalProperty: 'total',
			successProperty: 'success',
			reader: 'json'
			}
		})
	);
	user_list.load();
	var portal_users_grid_selector = Ext.create('Ext.grid.Panel', {
		store: user_list,
		selModel: sm2,
		columns: [
			{text: 'UID', dataIndex: 'uid', flex: 1},
			{text: 'User Name', dataIndex: 'name', flex: 3},
			{header: 'Included', width:50, dataIndex: 'included',
					xtype: 'checkcolumn', renderer: myCB2}
		],
		bbar: Ext.create('Ext.PagingToolbar', {
			store: user_list,
			displayInfo: true,
			listeners: {
				beforechange: function(tb,pgnum) {
					var my_store = Ext.data.StoreManager.lookup('user_list');
					var my_store2 = Ext.data.StoreManager.lookup('user_list_selection');
					var count=my_store.count();
					for(var i=0; i<count; ++i) {
						var r=my_store.getAt(i);
						var included=r.get('included');
						var uid=r.get('uid');
						var rec_n=my_store2.find('uid',uid);
						if(rec_n != -1) {
							var selected_rec=my_store2.getAt(rec_n);
							selected_rec.set('included',included);
							console.log("Set " + uid + " included: " + included);
						} else {
							my_store2.add({uid: uid, included: included});
							console.log("Added " + uid + " included: " + included);
						}
					}
				},
				change: function(tb,pgdata) {
					// Update the user_list_selection details with the current
					// record details...
					var my_sm = this.up('gridpanel').getSelectionModel();
					var gridp = this.up('gridpanel');
					gridp.show();
					// my_sm.setLocked(false);
					var my_store = Ext.data.StoreManager.lookup('user_list');
					var my_store2 = Ext.data.StoreManager.lookup('user_list_selection');
					var count=my_store.count();
					console.log("store_count2: " + my_store.count());
					for(var i=0; i<count; ++i) {
						var r=my_store.getAt(i);
						var included=r.get('included');
						var uid=r.get('uid');
						var rec_n=my_store2.find('uid',uid);
						if(rec_n == -1) {
							my_store2.add({uid: uid, included: included});
							console.log("Added2 " + uid + " included: " + included);
						} else {
							var r2=my_store2.getAt(rec_n);
							r2.set('included',r2.get('included'));
							console.log('Set2 ' + uid + ' included: ' + r2.get('included'));
						}
					}
				},
			},
			displayMsg: 'Displaying users {0} - {1} of {2}',
			emptyMsg: "No users defined"}),
		fbar: [
			{
				xtype: 'textfield',
				name: 'user_filter',
				fieldLabel: 'Filter',
				enableKeyEvents: true,
				id: 'portal_edit_tab3_filter'
			},
			{
				xtype: 'button',
				text: 'Filter',
				handler: function() {
					var tf = Ext.getCmp("portal_edit_tab3_filter");
					var filter_text = tf.getValue();
					var user_list=Ext.data.StoreManager.lookup('user_list');
					// ensure select/deselect don't update our list...
					var my_sm2 = this.up('gridpanel').getSelectionModel();
					// my_sm2.setLocked(true);
					GRI_glob_portal_user_list_updating=1;
					user_list.clearFilter(true);
					user_list.filter('name',filter_text);
					user_list.load();
					GRI_glob_portal_user_list_updating=0;
					// my_sm2.setLocked(false);
				}
			}
		]
	});
	var tf = Ext.getCmp("portal_edit_tab3_filter");
	var tabs = Ext.createWidget('tabpanel', {
		id: 'portalEditTabs',
		defaults: {
			bodypadding: 10
		},
		items: [{
			layout: 'fit',
			title: 'Basic Details',
			closable: false,
			disabled: true,
			// items: [{
					// region: 'center',
					// xtype: 'tbtext',
					// height: 50,
					// text: "This tab contains the basic portal details.",
			// }]
			id: 'portalEditTabs_t1',
			items: form_tab1,
		}, {
			layout: 'fit',
			title: 'Reports Subscribed',
			closable: false,
			// disabled: true,
			id: 'portalEditTabs_t2',
			items: reports_grid_selector,
			listeners: {
				activate: function(tab) {
					tab.setLoading("Retrieving ...");
					Remote_Actions.get_all_reports(
						function(provider,response) {
							var ds=Ext.data.StoreManager.lookup('portals_reports_grid');
							var res=response.result;
							if(res.error!=undefined) {
								append_status_text(res.error);
							} else {
								ds.removeAll();
								var trec=res.reports.length;
								for( var i=0; i<trec; ++i) {
									ds.add({
										rhost: res.reports[i].host,
										rfile: res.reports[i].name,
										rname: res.reports[i].title,
										rtype: res.reports[i].type,
										rcount: 0
									});
								}
								var tab = Ext.getCmp("portalEditTabs_t2");
								tab.setLoading(false);
								tab.enable();
							}
						}
					)
				}
			}
		}, {
			layout: 'fit',
			title: 'Allowed Users',
			closable: false,
			// disabled: true,
			id: 'portalEditTabs_t3',
			items: portal_users_grid_selector
		}, {
			title: 'Advanced Security',
			closable: false
		}]
	});

	var win_edit_portal = Ext.create('Ext.Window', {
		title: title,
		// width: 600,
		// height: 400,
		// x: 30,
		// y: 30,
		id: 'editPortalWindow',
		modal: true,
		// renderTo: document.body,
		headerPosition: 'top',
		// layout: 'border',
		layout: 'fit',
		items: tabs,
		fbar: [
			 { 	xtype: 'button', text: 'Cancel',
				handler: function() {
					this.up('window').destroy();
				} },
			 { xtype: 'button', text: 'Save',
				handler: function() {
					// Need to grab a list of 'included' reports first...
					// taking into account any set in the current panel
					var my_store = Ext.data.StoreManager.lookup('all_reports_grid');
					var my_store2 = Ext.data.StoreManager.lookup('report_list_selection');
					var count=my_store.count();
					for(var i=0; i<count; ++i) {
						var r=my_store.getAt(i);
						var included=r.get('included');
						var filename=r.get('filename');
						var reptype=r.get('reptype');
						var rfile=r.get('rfile');
						var rec_n=my_store2.find('rfile',rfile);
						if(rec_n != -1) {
							var selected_rec=my_store2.getAt(rec_n);
							selected_rec.set('selected',included);
						} else {
							my_store2.add({rfile: rfile, reptype: reptype, selected: included, filename: filename});
						}
					}
					my_store = Ext.data.StoreManager.lookup('user_list');
					my_store2 = Ext.data.StoreManager.lookup('user_list_selection');
					count=my_store.count();
					for(var i=0; i<count; ++i) {
						var r=my_store.getAt(i);
						var included=r.get('included');
						var uid=r.get('uid');
						var rec_n=my_store2.find('uid',uid);
						if(rec_n != -1) {
							var selected_rec=my_store2.getAt(rec_n);
							selected_rec.set('included',included);
						} else {
							my_store2.add({uid: uid, included: included});
						}
					}
					// Just use my_store2 to send a list of changes to reports
					// selected - since might not have paged in all reports...
					my_store2 = Ext.data.StoreManager.lookup('report_list_selection');
					count=my_store2.count();
					var reports_updated=[];
					var users_updated=[];
					for(var i=0; i<count; ++i) {
						var r=my_store2.getAt(i);
						var selected=r.get('selected');
						selected=selected==true ? 1 : 0;
						var rfile=r.get('rfile');
						var filename=r.get('filename');
						var reptype=r.get('reptype');
						reports_updated.push( {filename: filename, selected: selected, reptype: reptype} );
					}
					my_store2 = Ext.data.StoreManager.lookup('user_list_selection');
					count=my_store2.count();
					for(var i=0; i<count; ++i) {
						var r=my_store2.getAt(i);
						var included=r.get('included');
						included=included==true ? 1 : 0;
						var uid=r.get('uid');
						users_updated.push( {uid: uid, included: included} );
					}
					// Async update request
					var my_window=this.up('window');
					my_window.setLoading('Updating ...');
					Remote_Actions.update_portal_reports(portal,reports_updated,users_updated,
						function(provider,response) {
							var res=response.result;
							if(res.error!=undefined) {
								append_status_text(res.error);
								my_alert(res.error,'E','Failed to Update portal');
							}	
							my_window.destroy();
						}
					);
				}
			}
		]
	});

	var tab = Ext.getCmp('portal_edit_tab1');
	win_edit_portal.show();
	tab.setLoading("Retrieving ...");

	// Load the data for the form now... (async...)

	Remote_Actions.get_portal_details(portal,
		function(provider,response) {
			var form = Ext.getCmp('portal_edit_tab1').getForm();
			var res=response.result;
			if(res.error!=undefined) {
				append_status_text(res.error);
			} else {
				var vv = {};
				if(res.filename != undefined) {
					vv.portalname = res.filename;
				}
				if(res.title != undefined) {
					vv.portaltitle = res.title;
				}
				if(res.template != undefined) {
					vv.portaltemplate = res.template;
				}
				form.setValues(vv);
				var tab = Ext.getCmp('portal_edit_tab1'); // panel
				tab.setLoading(false);
				var tab = Ext.getCmp('portalEditTabs_t1'); // tab panel
				// We need to take the list of uid's and pop into the
				// user_list_selection to indicate which users have
				// set for the portal currently...
				var my_store = Ext.data.StoreManager.lookup('user_list_selection');
				for(var i=0; i<res.users.length; i++) {
					my_store.add( {
						uid: res.users[i],
						selected: 1
					});
				}
				tab.enable();
			}
		}
	);
}

function show_portal_info_chart1(portal_name,my_store,what) {
	// which is TOP for top 10 at moment
	var h =  this.innerHeight;
	var w = this.innerWidth;
	var whatname = 'rcount';
	var whattitle = 'Report Count Chart';
	var whataxis = 'Total Reports';
	var whatformat = '0';
	if(what == "size") {
		whatname = 'rsize';
		whattitle = 'Storage Allocation Chart';
		whataxis = 'Total KB Allocated';
		whatformat = '0 Kb';
	}
	// Dump out some store details...
	my_store.each( function(rec) {
		var f = rec.fields;
		var f2 = f.keys;
		for(var i=0; i<f2.length; ++i) {
			var fie = f2[i];
			// console.log('Field ' + fie + ': ' + rec.get(fie));
		}
	});
	var portals_info_chart1 = Ext.create('Ext.Window', {
		title: 'Portal Reports Overview - ' + whattitle,
		width: w-2,
		height: h-2, 
		maximizable: true,
		modal: true,
		renderTo: document.body,
		layout: 'fit',
		items: {
			id: 'info_chart1',
			xtype: 'chart',
			shadow: true,
			animate: true,
			store: my_store,
			axes: [{
				type: 'Numeric',
				position: 'bottom',
				fields: [whatname],
				label: Ext.util.Format.numberRenderer(whatformat),
				title: whataxis,
				grid: true,
				minimum: 0
			},{
				type: 'Category',
				position: 'left',
				fields: ['rname'],
				title: 'Report Name'
			}],
			series: [{
				type: 'bar',
				axis: 'bottom',
				highlight: true,
				label: {
					display: 'insideEnd',
					field: whatname,
					renderer: Ext.util.Format.numberRenderer(whatformat),
					orientation: 'horizontal',
					'text-anchor': 'middle'
				},
				xField: 'rname',
				yField: whatname
			}]
		}
	});
	portals_info_chart1.show();
}

// This should show a dialogue window with the portal details
// you are trying to gain access to along with the 'Request Access'
// and 'Cancel' buttons.

function request_portal_access_form(portal) {
	console.log("Showing portal: " + portal);

	// Define the information as a form, though really we
	// use it for formatting and disable all the fields

	var h =  this.innerHeight;
	var w = this.innerWidth;
	var portal_request_window = Ext.create('Ext.Window', {
		title: 'Request Access - ' + portal,
		width: 400,
		height: 400, 
		// x: 1,
		// y: 1,
		id: 'portalRequestWindow',
		modal: true,
		renderTo: document.body,
		headerPosition: 'top',
		layout: {
			type: 'table',
			columns: 4
		},
		items: [{
			xtype: 'label',
			text: 'Portal:',
		},{
			xtype: 'label',
			text: '    ',
		},{
			xtype: 'label',
			colspan: 2,
			text: '',
			id: 'portalsRequestWindowName',
		},{
			colspan: 4,
			xtype: 'label',
			text: '----- ',
		},{
			xtype: 'label',
			text: 'Owners:',
		},{
			xtype: 'label',
			text: '    ',
		},{
			xtype: 'label',
			colspan: 2,
			text: '',
			id: 'portalsRequestWindowOwners',
		},{
			colspan: 4,
			xtype: 'label',
			text: '----- ',
		},{
			xtype: 'label',
			text: 'Voters:',
		},{
			xtype: 'label',
			text: '    ',
		},{
			xtype: 'label',
			colspan: 2,
			text: '',
			id: 'portalsRequestWindowVoters',
		},{
			colspan: 4,
			xtype: 'label',
			text: '----- ',
		},{
			colspan: 4,
			xtype: 'textarea',
			fieldLabel: 'Justification',
			width: 300,
			name: 'justification',
			anchor: '100%',
			id: 'portalsRequestWindowJustification',
			grow: true
		},{
			colspan: 4,
			xtype: 'label',
			text: '----- ',
		},{
			colspan: 4,
			xtype: 'label',
			text: 'Please entry some justification text and if you wish to gain access click on "Request Access".'
		}],
		buttons: [
			{
				text: 'Request Access',
				handler: function() {
					var win=this.up('window');
					win.setLoading("Sending Request...");
					var txt=Ext.getCmp('portalsRequestWindowJustification');
					var str=txt.getRawValue();
					// We need the user id, portal and requestor text
					// to generate a access request...
					Remote_Actions.register_portal_access_request(portal,str,
						function(provider,response) {
							var cmp = Ext.getCmp('portalsRequestWindowName');
							var res=response.result;
							if(res.error!=undefined) {
								append_status_text(res.error);
							} else {
								my_alert("Request " + res.id + " has been raised for you.\nPlease use this reference in call correspondence.");
							}
							win.close();
						}
					);
				}
			},{
				text: 'Cancel',
				handler: function() {
					this.up('window').close();
				}
			}]
	});
	// Actually force size and position...
	portal_request_window.setSize(400,400);
	portal_request_window.center();
	portal_request_window.show();
	portal_request_window.setLoading("Retrieving...");
	// populate names and then rest of data...
	// var statusbar = Ext.getCmp("status_bar");

	Remote_Actions.get_portal_details(portal,
		function(provider,response) {
			var cmp = Ext.getCmp('portalsRequestWindowName');
			var res=response.result;
			if(res.error!=undefined) {
				append_status_text(res.error);
			} else {
				if(res.title != undefined) {
					cmp.setText(res.title);
				}
				if(res.owners.length>0) {
					var XX=new Array();
					Remote_Actions.map_uids(res.owners,
						function(provider,response) {
							var XX=new Array();
							var res=response.result;
							var s="";
							for(uid in res.uids) {
								XX.push(res.uids[uid].email);
								if(s.length>0) {
									s=s + " , " + res.uids[uid].email;
								} else {
									s=res.uids[uid].email;
								}
							}
							var cmp = Ext.getCmp('portalsRequestWindowOwners');
							cmp.setText(s)
						}
					);
				}
				if(res.voters.length>0) {
					var XX=new Array();
					Remote_Actions.map_uids(res.voters,
						function(provider,response) {
							var XX=new Array();
							var res=response.result;
							var s="";
							for(uid in res.uids) {
								XX.push(res.uids[uid].email);
								if(s.length>0) {
									s=s + " , " + res.uids[uid].email;
								} else {
									s=res.uids[uid].email;
								}
							}
							var cmp = Ext.getCmp('portalsRequestWindowVoters');
							cmp.setText(s)
						}
					);
				}
			}
			portal_request_window.setLoading(false);
		}
	);
}

function view_available_portals_window(portal,dl_report,dl_rep_mtime) {
	var portals_reports_grid=Ext.data.StoreManager.lookup('portals_reports_grid');
	var portal_reports_list_grid=Ext.data.StoreManager.lookup('portal_reports_list_grid');

	var is_report_admin=0;
	var xml_tooltip='View Raw Report Configuration';
	var editview_tooltip='View Report Configuration';
	var my_roles=getCookieElement("GRI2_prefs","ROLES");
	var my_roles_A=my_roles.split(",");
	for(var i=0; i<my_roles_A.length; i++) {
		if(my_roles_A[i]=="report_admin") {
			is_report_admin=1;
			xml_tooltip='View/Edit Raw Report Configuration';
			editview_tooltip='View/Edit Report Configuration';
		}
	}

	GRI_glob_portal_meta_reports_info={};
	portals_reports_grid.removeAll();
	portal_reports_list_grid.removeAll();
	var h =  this.innerHeight;
	var w = this.innerWidth;
	var others=[{
			icon: 'resources/images/viewreport.gif',
			tooltip: 'View Report',
			disabled: false,
			handler: function(grid, rowIndex, colIndex) {
				var rec = portal_reports_list_grid.getAt(rowIndex);
				view_report_content(rec);
			}
		},{
			icon: 'resources/images/deeplink.gif',
			tooltip: 'Deeplink to Report',
			disabled: false,
			handler: function(grid, rowIndex, colIndex) {
				var rec = portal_reports_list_grid.getAt(rowIndex);
				var rep_name=rec.get('report');
				var rep_mtime=rec.get('rmtime');
				show_deeplink_dialog(portal,rep_name,rep_mtime);
			}
		}];
	if(griglobs_ALLOW_EMAIL == 1 && griglobs_EMAIL_ADDR != undefined) {
		others.push({
			icon: 'resources/images/viewreport.gif',
			tooltip: 'Email Report to ' + griglobs_EMAIL_ADDR,
			disabled: false,
			handler: function(grid, rowIndex, colIndex) {
				var rec = portal_reports_list_grid.getAt(rowIndex);
				view_report_content(rec,1);
			}
		});
	}
	var portals_view_window = Ext.create('Ext.Window', {
		title: 'Available Reports - ' + portal,
		width: w-2,
		height: h-2, 
		maximizable: true,
		x: 1,
		y: 1,
		id: 'portalsWindow',
		modal: true,
		renderTo: document.body,
		headerPosition: 'top',
		layout: 'border',
		items: [{
			region: 'center',
			layout: {
				type: 'vbox',
				align: 'stretch'
			},
			items: [{
				flex: 1,
				id: 'portal_reports_list',
				xtype: 'grid',
				store: portals_reports_grid,
				viewConfig: {
					stripeRows: true,
					trackOver: false
				},
			tbar: [{
				// height: 32,
				// width: 32,
				icon: 'resources/images/chart.bmp',
				text: 'Counts',
				iconAlign: 'top',
				id: 'portal_view_chart_btn1',
				tooltip: 'Report Counts Chart',
				disabled: true,
				listeners: {
					click: function() {
						show_portal_info_chart1(portal,portals_reports_grid,'count');
					}
				}
			},{
				// height: 32,
				// width: 32,
				icon: 'resources/images/chart.bmp',
				text: 'Sizes',
				iconAlign: 'top',
				id: 'portal_view_chart_btn2',
				tooltip: 'Report Storage Chart',
				disabled: true,
				listeners: {
					click: function() {
						show_portal_info_chart1(portal,portals_reports_grid,'size');
					}
				}
			},{
				// height: 32,
				// width: 32,
				icon: 'resources/images/refresh.gif',
				iconAlign: 'top',
				id: 'portal_view_chart_btn3',
				text: 'Refresh',
				tooltip: 'Refresh Window Contents',
				cls: 'x-btn-text-icon',
				disabled: true,
				listeners: {
					click: function() {
						populate_portal_reports_list(portal);
					}
				}
			},{
				icon: 'resources/images/deeplink.gif',
				iconAlign: 'top',
				id: 'portal_generate_deeplink',
				text: 'Deeplink',
				tooltip: 'Generate Deeplink to Portal',
				cls: 'x-btn-text-icon',
				disabled: true,
				listeners: {
					click: function() {
						show_deeplink_dialog(portal);
					}
				}
			}],
				columns: [
					{header: 'Description', flex:4, dataIndex: 'rname', renderer: _reports_list_grid_desc},
					{header: 'Content Type', flex:1, dataIndex: 'rtype'},
					{header: 'Host', flex:1, dataIndex: 'rhost'},
					{header: 'Latest Report', flex:1, dataIndex: 'rdate', renderer: _reports_list_grid_render_date},
					{header: 'Report Count', flex:1, dataIndex: 'rcount'},
					{header: 'Storage', flex:1, dataIndex: 'rsize', hidden: true, renderer: _reports_list_grid_render_size},
					{header: 'Directory', flex:1, hidden: true, dataIndex: 'rdir'},
					{header: 'Pattern', flex:1, hidden: true, dataIndex: 'rpattern'},
					{xtype: 'actioncolumn', flex:1, sortable: false,
						text: 'Actions',
						items: [{
							icon: 'resources/images/access.gif',
							tooltip: 'Open Report Listing',
							disabled: false,
							handler: function(grid, rowIndex, colIndex) {
								var rec = portals_reports_grid.getAt(rowIndex);
								view_available_reports(portal,rec);
							}
						},{
							icon: 'resources/images/admin.gif',
							tooltip: editview_tooltip,
							disabled: false,
							handler: function(grid, rowIndex, colIndex) {
								var rec = portals_reports_grid.getAt(rowIndex);
								edit_add_report_window(rec,is_report_admin,undefined);
							}
						},{
							icon: 'resources/images/xml.gif',
							tooltip: xml_tooltip,
							disabled: false,
							handler: function(grid, rowIndex, colIndex) {
								var rec = portals_reports_grid.getAt(rowIndex);
								view_available_report_config(portal,rec,is_report_admin);
							}
						},{
							icon: 'resources/images/deeplink.gif',
							tooltip: 'Deeplink to Report List',
							disabled: false,
							handler: function(grid, rowIndex, colIndex) {
								var rec = portals_reports_grid.getAt(rowIndex);
								var rep_name=rec.get('rname');
								show_deeplink_dialog(portal,rep_name);
							}
						},{
							icon: 'resources/images/deeplink_meta.gif',
							tooltip: 'Meta Deeplink to Latest Report',
							disabled: false,
							handler: function(grid, rowIndex, colIndex) {
								var rec = portals_reports_grid.getAt(rowIndex);
								var rep_name=rec.get('rname');
								show_deeplink_dialog(portal,rep_name,'-1');
							}
						} ]
					}
				]
			},{
				flex: 1,
				id: 'portal_reports_list_reps',
				xtype: 'grid',
				store: portal_reports_list_grid,
				viewConfig: {
					stripeRows: true,
					trackOver: false
				},
				columns: [
					{header: 'Date', flex:1, dataIndex: 'rdate', renderer: _reports_list_grid_render_date},
					{header: 'Size', flex:1, dataIndex: 'rsize', renderer: _reports_list_grid_render_size},
					{xtype: 'actioncolumn', flex:1, sortable: false,
						text: 'Actions',
						items: others
					}
				],
				bbar: Ext.create('Ext.PagingToolbar', {
					store: portal_reports_list_grid,
					displayInfo: true,
					// listeners: {
						// beforechange: function(tb,pgnum) {
							// var my_sm = this.up('gridpanel').getSelectionModel();
							// my_sm.setLocked(true);
							// GRI_glob_portal_report_list_updating=1;
						// },
						// change: function(tb,pgdata) {
							// var my_sm = this.up('gridpanel').getSelectionModel();
							// var gridp = this.up('gridpanel');
							// gridp.show();
							// my_sm.setLocked(false);
							// // Get hold of the selection - and 'select' records to
							// // overcome problems with paging checkbox selection model
							// var my_store = Ext.data.StoreManager.lookup('report_list_selection');
							// var report_list=Ext.data.StoreManager.lookup('all_reports_grid');
							// // Any uid's in my_store with selected==1 should
							// // set selection in user_list to ensure// If view is correct.
							// var count=my_store.count();
							// console.log(my_store);
							// for(var i=0; i<count; ++i) {
								// var r=my_store.getAt(i);
								// var rfile=r.get('rfile');
								// var sel=r.get('selected');
								// if(sel==1) {
									// var idx=report_list.find('rfile',rfile);
									// if(idx>-1) {
										// var rec = report_list.getAt(idx)
										// my_sm.select(idx,1,true);
									// }
								// }
							// }
							// GRI_glob_portal_report_list_updating=0;
						// },
					// },
					displayMsg: 'Displaying reports {0} - {1} of {2}',
					emptyMsg: "No reports defined"}),
			}]
		}]
	});
	// Actually force size and position...
	portals_view_window.setPosition(1,1);
	portals_view_window.setSize(w-2,h-2);
	// portals_view_window.center();
	portals_view_window.show();
	// populate names and then rest of data...
	populate_portal_reports_list(portal,dl_report,dl_rep_mtime);
}

function edit_included_reports(rec) {
	my_alert("edit_included_reports",'E',"Function not implemented yet.");
}
function edit_included_users(rec) {
	my_alert("edit_included_users",'E',"Function not implemented yet.");
}

function populate_portal_reports_list(portal,dl_report,dl_rep_mtime) {
	var myGrid = Ext.getCmp('portalsWindow');
    myGrid.setTitle('Available Reports - ' + portal);
	var psg = Ext.getCmp("portal_reports_list");
	// var statusbar = Ext.getCmp("status_bar");
	var ds=Ext.data.StoreManager.lookup('portal_reports_list_grid');
	ds.removeAll();
	var ds=Ext.data.StoreManager.lookup('portals_reports_grid');
	ds.removeAll();
	psg.setLoading("Retrieving...");
	// ds.suspendEvents();
	Remote_Actions.get_portal_report_names(portal,
		function(provider,response) {
			var res=response.result;
			var ds=Ext.data.StoreManager.lookup('portals_reports_grid');
			var arLen=res.length;
			// psg.setLoading(false);
			for( var i=1,len=arLen; i<len; ++i) {
				if(res[i].error != undefined) {
					append_status_text(res[i].error);
					continue;
				}
				ds.add({
					entry_type: "R",
					rfile: res[i].report,
					rname: res[i].name,
					rtype: res[i].type,
					rhost: res[i].host,
					display_name: '',
					rsize: 0,
					rpattern: '',
					rdir: '',
					rdate: '',
					rcount: 0,
				});
				// Also async request to get further details ...
				Remote_Actions.get_portal_report_details(portal,res[i].report,
					function(provider,response) {
						var res2=response.result;
						if(res2.error!=undefined) {
							append_status_text(res2.error);
						} else {
							var my_index = ds.findExact("rfile",res2.report);
							var rec = ds.getAt(my_index);
							rec.set("rdate",res2.date);
							rec.set("rcount",parseInt(res2.count));
							rec.set("rsize",parseInt(res2.size));
							rec.set("rdir",res2.directory);
							rec.set("rpattern",res2.pattern);
							rec.set("display_name",res2.display_name);
							rec.set("attrs",res2.attrs);
							rec.set("raw_xml",base64_decode(res2.rawxml));
							rec.set("dynamic_convert_type",res2.dynamic[0]);
						}
					}
				);
			}
			// ds.resumeEvents();
			var chart_button = Ext.getCmp('portal_view_chart_btn1');
			chart_button.enable();
			var chart_button = Ext.getCmp('portal_view_chart_btn2');
			chart_button.enable();
			var chart_button = Ext.getCmp('portal_view_chart_btn3');
			chart_button.enable();
			var chart_button = Ext.getCmp('portal_generate_deeplink');
			chart_button.enable();
			console.log("Count of elements in reports datastore:" + ds.count());
		}
	);
	// Above gets the real reports (if any) - now get meta reports ... if any...
	Remote_Actions.get_portal_meta_report_names(portal,
		function(provider,response) {
			var res=response.result;
			var ds=Ext.data.StoreManager.lookup('portals_reports_grid');
			if(res[0] != "OK") {
				append_status_text(res[1]);
				psg.setLoading(false);
				return;
			}
			// ds.suspendEvents();
			var arLen=res.length;
			for( var i=1,len=arLen; i<len; ++i) {
				if(res[i].error != undefined) {
					append_status_text(res[i].error);
					continue;
				}
				console.log("Attempting to add details for report:" + res[i].name);

				ds.add({
					entry_type: "M",
					rfile: res[i].report,
					rname: res[i].name,
					rtype: res[i].type,
					rhost: res[i].host.join(","),
				    rsize: 0,
					rpattern: '',
					rdir: '',
					rdate: '',
					rcount: 0,
				});
				// Also async request to get further details ...
				Remote_Actions.filter_meta_reports(portal,res[i].report,0,
					function(provider,response) {
						var res2=response.result;
						console.log("filter_meta_reports:");
						console.log(res2);
						if(res2.error!=undefined) {
							append_status_text(res2.error);
						} else {
							var my_index = ds.findExact("rfile",res2.report);
							var rec = ds.getAt(my_index);
							rec.set("rcount",parseInt(res2.count));
							rec.set("raw_xml",base64_decode(res2.rawxml));
							// rec.set("rsize",parseInt(res2.size));
							// rec.set("rdir",res2.directory);
							rec.set("rpattern","N/A - Meta Report");
							rec.set("attrs","N/A - Meta Report");
							rec.set("dynamic_convert_type","N/A - Meta Report");
							// Might be worth recording this info .. so when clicking 
							// on a report it populates it without another server call!!
							GRI_glob_portal_meta_reports_info[res2.report]=res2;
							// Set rdate based on fmtime > from all records
							var ii=-1; var iis="";
							for(var i=0; i<res2.records.length; i++) {
								var yy=parseInt(res2.records[i].fmtime);
								if(yy>ii) { ii=yy; iis=res2.records[i].fdate_str; }
							}
							rec.set("rdate",iis);
						}
					}
				);
			}
			psg.setLoading(false);
			if(dl_report !== undefined) {
				var portals_reports_grid=Ext.data.StoreManager.lookup('portals_reports_grid');
				var rec_no = portals_reports_grid.findExact('rfile',dl_report);
				if(rec_no!=-1) {
					var rec = portals_reports_grid.getAt(rec_no);
					view_available_reports(portal,rec,dl_rep_mtime);
				} else {
					rec_no = portals_reports_grid.findExact('rname',dl_report);
					if(rec_no!=-1) {
						var rec = portals_reports_grid.getAt(rec_no);
						view_available_reports(portal,rec,dl_rep_mtime);
					} else {
						console.log("Unable to get details for report: " + dl_report);
					}
				}
			}
		}
	);
}

// type is I or E
function my_alert(txt,type,title) {
	var ii;
	if(type == undefined) {
		type="I";
	}
	if(type == "I") {
		ii=Ext.Msg.INFO;
		if(title == undefined) {
			title="Information";
		}
	} else {
		ii=Ext.Msg.ERROR;
		if(title == undefined) {
			title="Error";
		}
	}
	Ext.Msg.show({
		title: title,
		msg: txt,
		modal: true,
		icon: ii,
		buttons: Ext.Msg.OK
	});
}

function show_deeplink_dialog(portal,report,rep_mtime) {
	var pl;
	var title=undefined;
	if(rep_mtime !== undefined) {
			pl='p:' + base64_encode(portal) + ',r:' + base64_encode(report) + ',m:' + base64_encode(rep_mtime);
			title="Link to instance " + rep_mtime + " of Report " + report;
	} else {
		if(report !== undefined) {
			pl='p:' + base64_encode(portal) + ',r:' + base64_encode(report);
			title="Link to Report " + report;
		} else {
			pl='p:' + base64_encode(portal);
			title="Link to Portal " + portal;
		}
	}
	var pl=window.location.href + '?dl=' + base64_encode(pl);
	var h =  this.innerHeight;
	var w = this.innerWidth;
	var deeplink_window = Ext.create('Ext.Window', {
		title: title,
		width: w-100,
		// height: h-2, 
		// x: 1,
		// y: 1,
		id: 'deeplink_dialog',
		modal: true,
		renderTo: document.body,
		headerPosition: 'top',
		layout: 'anchor',
		items: [{
			xtype: 'label',
			text: 'Link requested is:'
		},{
			xtype: 'textarea',
			id: 'deeplink_dialog_ta',
			name: 'deeplink_dialog_ta',
			anchor: '100%',
			grow: true,
			value: pl,
			readOnly: true,
			padding: 0,
			flex: 1
		}],
		bbar: [
			{ xtype: 'button', text: 'Close',
				listeners: {
					click: function() {
						this.up('window').close();
					}
				}
			}
		]
	});
	deeplink_window.show();
}

// Define datastores up front rather than in functions to
// overcome any dependencies ...

Ext.define('reports_list_Model',{
	extend: 'Ext.data.Model',
	fields: [
		{name: 'entry_type',  type: 'string'},
		{name: 'rfile',  type: 'string'},
		{name: 'rname',  type: 'string'},
		{name: 'rtype',  type: 'string'},
		{name: 'reptype',  type: 'string'}, // report type M = meta, otherwise normal...
		{name: 'taction',type: 'string'},
		{name: 'rdate', type: 'string'},
		{name: 'rpattern',   type: 'string'},
		{name: 'rdir',   type: 'string'},
		{name: 'rhost', type: 'string'},
		{name: 'attrs', type: 'string'},
		{name: 'dynamic_convert_args', type: 'string'},
		{name: 'dynamic_convert_type', type: 'string'},
		{name: 'dynamic_convert_desc', type: 'string'},
		{name: 'display_name', type: 'string'},
		{name: 'raw_xml', type: 'string'},
		{name: 'rsize', type: 'int'},
		{name: 'rcount', type: 'int'},
		{name: 'included', type: 'bool'},
		{name: 'filename', type: 'string'}
	],
	idProperty: 'filename'
});

Ext.create('Ext.data.ArrayStore', {
	storeId: 'portals_reports_grid',
	model: 'reports_list_Model',
	data: [ ]
});

Ext.create('Ext.data.Store', {
	storeId: 'all_reports_grid',
	model: 'reports_list_Model',
	pageSize: 200,
	remoteSort: true,
	buffered: false,
	proxy: {
		type: 'ajax',
		url: 'cgi_bin/get_reports.pl',
		reader: {
			root: 'reports',
			totalProperty: 'total',
			successProperty: 'success'
		}
	}
});

Ext.define('user_list_Model',{
	extend: 'Ext.data.Model',
	fields: [
		{name: 'uid',  type: 'string'},
		{name: 'name',  type: 'string'},
		{name: 'included', type: 'bool'},
	],
	idProperty: 'uid'
});

Ext.create('Ext.data.Store', {
	storeId: 'user_list',
	model: 'user_list_Model',
	pageSize: 200,
	remoteSort: true,
	buffered: false,
	proxy: {
		type: 'ajax',
		url: 'cgi_bin/get_users.pl',
		reader: {
			root: 'users',
			totalProperty: 'total',
			successProperty: 'success'
		}
	}
});

Ext.define('report_instance_list', {
	extend: 'Ext.data.Model',
	fields: [
		{name: 'rfile', type: 'string'},
		{name: 'rdate', type: 'string'},
		{name: 'rsize', type: 'int'},
		{name: 'rmtime', type: 'int'},
		{name: 'portal', type: 'string'},
		{name: 'report', type: 'string'}
	]
});

Ext.create('Ext.data.ArrayStore', {
	storeId: 'portal_reports_list_grid',
	model: 'report_instance_list',
	pageSize: 200,
	data: []
});
var login_user_name=undefined;
// Application's initialization
Ext.onReady(function() {
	var dl_portal=undefined;
	var dl_report=undefined;
	var dl_rep_mtime=undefined;
	// Check for deeplink cookie; act on it and remove it!
	var cv2 = getCookie('GRI2SD');
	if(cv2 != undefined) {
		// deep link format base64 of: p:encportalname[,r:encreportname[,m:time]]
		var action="Unknown";
		if(cv2=="alerts") {
			action="Show Alerts";
		}
		if(cv2=="prefs") {
			action="Show Preferences";
		}

		alert("Deep link! Action=" + action);
		// Ext.util.Cookies.clear('GRI2SD','/');
	}
	var cv = getCookie('GRI2DL');
	if(cv != undefined) {
		// deep link format base64 of: p:encportalname[,r:encreportname[,m:time]]
		var dcv=base64_decode(cv);
		var dcv_bits=dcv.split(",");
		if(dcv_bits.length>0) {
			var a=dcv_bits[0].split(':');
			dl_portal=base64_decode(a[1]);
		}
		if(dcv_bits.length>1) {
			var a=dcv_bits[1].split(':');
			dl_report=base64_decode(a[1]);
		}
		if(dcv_bits.length>2) {
			var a=dcv_bits[2].split(':');
			dl_rep_mtime=base64_decode(a[1]);
		}
		alert("Deep link! portal=" + dl_portal + ",report=" + dl_report + ",mtime=" + dl_rep_mtime);
		Ext.util.Cookies.clear('GRI2DL','/');
	}
	Ext.QuickTips.init();
	var toplevel=main_layout();
	toplevel.show();
	login_window(dl_portal,dl_report,dl_rep_mtime);
});
